Check associated type satisfy their bounds
This was currently only happening due to eager normalization, which isn't possible if there's specialization or bound variables.
This commit is contained in:
parent
04e589ced8
commit
d660dbc630
@ -4,15 +4,17 @@
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
|
||||
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||
use rustc_middle::ty::util::ExplicitSelf;
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
|
||||
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
|
||||
|
||||
use super::{potentially_plural_count, FnCtxt, Inherited};
|
||||
use std::iter;
|
||||
|
||||
/// Checks that a method from an impl conforms to the signature of
|
||||
/// the same method as declared in the trait.
|
||||
@ -1057,13 +1059,15 @@ fn nested_visit_map(
|
||||
let _: Result<(), ErrorReported> = (|| {
|
||||
compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
|
||||
|
||||
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)
|
||||
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
|
||||
|
||||
compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
|
||||
})();
|
||||
}
|
||||
|
||||
/// The equivalent of [compare_predicate_entailment], but for associated types
|
||||
/// instead of associated functions.
|
||||
fn compare_type_predicate_entailment(
|
||||
fn compare_type_predicate_entailment<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_ty: &ty::AssocItem,
|
||||
impl_ty_span: Span,
|
||||
@ -1165,6 +1169,152 @@ fn compare_type_predicate_entailment(
|
||||
})
|
||||
}
|
||||
|
||||
/// Validate that `ProjectionCandidate`s created for this associated type will
|
||||
/// be valid.
|
||||
///
|
||||
/// Usually given
|
||||
///
|
||||
/// trait X { type Y: Copy } impl X for T { type Y = S; }
|
||||
///
|
||||
/// We are able to normalize `<T as X>::U` to `S`, and so when we check the
|
||||
/// impl is well-formed we have to prove `S: Copy`.
|
||||
///
|
||||
/// For default associated types the normalization is not possible (the value
|
||||
/// from the impl could be overridden). We also can't normalize generic
|
||||
/// associated types (yet) because they contain bound parameters.
|
||||
fn compare_projection_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ty: &ty::AssocItem,
|
||||
impl_ty: &ty::AssocItem,
|
||||
impl_ty_span: Span,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> Result<(), ErrorReported> {
|
||||
let is_gat = !tcx.generics_of(impl_ty.def_id).params.is_empty();
|
||||
if impl_ty.defaultness.is_final() && !is_gat {
|
||||
// For "final", non-generic associate type implementations, we
|
||||
// don't need this as described above.
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let param_env = tcx.param_env(impl_ty.def_id);
|
||||
|
||||
let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.container.id());
|
||||
let impl_ty_value = tcx.type_of(impl_ty.def_id);
|
||||
|
||||
// Map the predicate from the trait to the corresponding one for the impl.
|
||||
// For example:
|
||||
//
|
||||
// trait X<A> { type Y<'a>: PartialEq<A> } impl X for T { type Y<'a> = &'a S; }
|
||||
// impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; }
|
||||
//
|
||||
// For the `for<'a> <<Self as X<A>>::Y<'a>: PartialEq<A>` bound, this
|
||||
// function would translate and partially normalize
|
||||
// `[<Self as X<A>>::Y<'a>, A]` to `[&'a u32, &'x u32]`.
|
||||
let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
|
||||
let normalized_self = if !is_gat {
|
||||
// projection_predicates only includes projections where the
|
||||
// substs of the trait ref are exactly the trait's identity
|
||||
// substs, so we can simply return the value from the impl.
|
||||
impl_ty_value
|
||||
} else {
|
||||
let predicate_self_ty = predicate_substs.type_at(0);
|
||||
let impl_ty_substs = if let ty::Projection(p) = predicate_self_ty.kind {
|
||||
assert!(
|
||||
p.item_def_id == trait_ty.def_id,
|
||||
"projection_predicates returned predicate for the wrong type: {}",
|
||||
predicate_self_ty,
|
||||
);
|
||||
p.substs.rebase_onto(tcx, impl_trait_ref.def_id, impl_substs)
|
||||
} else {
|
||||
bug!(
|
||||
"projection_predicates returned predicate for the wrong type `{}`",
|
||||
predicate_self_ty,
|
||||
);
|
||||
};
|
||||
impl_ty_value.subst(tcx, impl_ty_substs)
|
||||
};
|
||||
|
||||
tcx.mk_substs(
|
||||
iter::once(normalized_self.into())
|
||||
.chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, impl_trait_ref.substs))),
|
||||
)
|
||||
};
|
||||
|
||||
tcx.infer_ctxt().enter(move |infcx| {
|
||||
let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
|
||||
let infcx = &inh.infcx;
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
|
||||
let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local());
|
||||
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
|
||||
let cause = ObligationCause::new(
|
||||
impl_ty_span,
|
||||
impl_ty_hir_id,
|
||||
ObligationCauseCode::ItemObligation(trait_ty.def_id),
|
||||
);
|
||||
|
||||
let predicates = tcx.projection_predicates(trait_ty.def_id);
|
||||
|
||||
debug!("compare_projection_bounds: projection_predicates={:?}", predicates);
|
||||
|
||||
for predicate in predicates {
|
||||
let concrete_ty_predicate = match predicate.kind() {
|
||||
ty::PredicateKind::Trait(poly_tr, c) => poly_tr
|
||||
.map_bound(|tr| {
|
||||
let trait_substs = translate_predicate_substs(tr.trait_ref.substs);
|
||||
ty::TraitRef { def_id: tr.def_id(), substs: trait_substs }
|
||||
})
|
||||
.with_constness(*c)
|
||||
.to_predicate(tcx),
|
||||
ty::PredicateKind::Projection(poly_projection) => poly_projection
|
||||
.map_bound(|projection| {
|
||||
let projection_substs =
|
||||
translate_predicate_substs(projection.projection_ty.substs);
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: ty::ProjectionTy {
|
||||
substs: projection_substs,
|
||||
item_def_id: projection.projection_ty.item_def_id,
|
||||
},
|
||||
ty: projection.ty.subst(tcx, impl_trait_ref.substs),
|
||||
}
|
||||
})
|
||||
.to_predicate(tcx),
|
||||
_ => bug!("unexepected projection predicate kind: `{:?}`", predicate),
|
||||
};
|
||||
|
||||
let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
|
||||
&mut selcx,
|
||||
param_env,
|
||||
normalize_cause.clone(),
|
||||
&concrete_ty_predicate,
|
||||
);
|
||||
|
||||
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
|
||||
|
||||
inh.register_predicates(obligations);
|
||||
inh.register_predicate(traits::Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
normalized_predicate,
|
||||
));
|
||||
}
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
|
||||
infcx.report_fulfillment_errors(errors, None, false);
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
||||
// Finally, resolve all regions. This catches wily misuses of
|
||||
// lifetime parameters.
|
||||
let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
|
||||
fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
|
||||
match impl_item.kind {
|
||||
ty::AssocKind::Const => "const",
|
||||
|
@ -0,0 +1,32 @@
|
||||
// Regression test for #68641
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait UnsafeCopy {
|
||||
type Item<'a>: Copy;
|
||||
|
||||
fn copy<'a>(item: &Self::Item<'a>) -> Self::Item<'a> {
|
||||
*item
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UnsafeCopy for T {
|
||||
type Item<'a> = T;
|
||||
//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut s = String::from("Hello world!");
|
||||
|
||||
let copy = String::copy(&s);
|
||||
|
||||
// Do we indeed point to the samme memory?
|
||||
assert!(s.as_ptr() == copy.as_ptr());
|
||||
|
||||
// Any use of `copy` is certeinly UB after this
|
||||
drop(s);
|
||||
|
||||
// UB UB UB UB UB!!
|
||||
println!("{}", copy);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68641-check-gat-bounds.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-68641-check-gat-bounds.rs:15:5
|
||||
|
|
||||
LL | trait UnsafeCopy {
|
||||
| ---------------- required by `UnsafeCopy`
|
||||
...
|
||||
LL | type Item<'a> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::marker::Copy> UnsafeCopy for T {
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
// Regression test for #68642
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait Fun {
|
||||
type F<'a>: Fn() -> u32;
|
||||
|
||||
fn callme<'a>(f: Self::F<'a>) -> u32 {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fun for T {
|
||||
type F<'a> = Self;
|
||||
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<fn() -> usize>::callme(|| 1);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68642-broken-llvm-ir.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68642-broken-llvm-ir.rs:15:5
|
||||
|
|
||||
LL | trait Fun {
|
||||
| --------- required by `Fun`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
|
||||
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
|
||||
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::ops::Fn<()>> Fun for T {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
// Regression test for #68643
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait Fun {
|
||||
type F<'a>: Fn() -> u32;
|
||||
|
||||
fn callme<'a>(f: Self::F<'a>) -> u32 {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fun for T {
|
||||
type F<'a> = Self;
|
||||
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
<fn()>::callme(|| {});
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68643-broken-mir.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68643-broken-mir.rs:15:5
|
||||
|
|
||||
LL | trait Fun {
|
||||
| --------- required by `Fun`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
|
||||
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
|
||||
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::ops::Fn<()>> Fun for T {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
// Regression test for #68644
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait Fun {
|
||||
type F<'a>: Fn() -> u32;
|
||||
|
||||
fn callme<'a>(f: Self::F<'a>) -> u32 {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fun for T {
|
||||
type F<'a> = Self;
|
||||
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<u8>::callme(0);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68644-codegen-selection.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68644-codegen-selection.rs:15:5
|
||||
|
|
||||
LL | trait Fun {
|
||||
| --------- required by `Fun`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
|
||||
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
|
||||
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::ops::Fn<()>> Fun for T {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
// Regression test for #68645
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait Fun {
|
||||
type F<'a>: Fn() -> u32;
|
||||
|
||||
fn callme<'a>(f: Self::F<'a>) -> u32 {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fun for T {
|
||||
type F<'a> = Self;
|
||||
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<&dyn Iterator<Item = u8>>::callme(&std::iter::once(1));
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68645-codegen-fulfillment.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68645-codegen-fulfillment.rs:15:5
|
||||
|
|
||||
LL | trait Fun {
|
||||
| --------- required by `Fun`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
|
||||
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
|
||||
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::ops::Fn<()>> Fun for T {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,22 @@
|
||||
// Regression test for #68656
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait UnsafeCopy<T: Copy> {
|
||||
type Item<'a>: std::ops::Deref<Target = T>;
|
||||
|
||||
fn bug<'a>(item: &Self::Item<'a>) -> () {
|
||||
let x: T = **item;
|
||||
&x as *const _;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
|
||||
type Item<'a> = T;
|
||||
//~^ ERROR type mismatch resolving `<T as std::ops::Deref>::Target == T`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<&'static str>::bug(&"");
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68656-unsized-values.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0271]: type mismatch resolving `<T as std::ops::Deref>::Target == T`
|
||||
--> $DIR/issue-68656-unsized-values.rs:16:5
|
||||
|
|
||||
LL | trait UnsafeCopy<T: Copy> {
|
||||
| ------------------------- required by `UnsafeCopy`
|
||||
...
|
||||
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
|
||||
| - this type parameter
|
||||
LL | type Item<'a> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
|
||||
|
|
||||
= note: expected type parameter `T`
|
||||
found associated type `<T as std::ops::Deref>::Target`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | impl<T: Copy + std::ops::Deref + std::ops::Deref<Target = T>> UnsafeCopy<T> for T {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -1,4 +1,3 @@
|
||||
// run-pass
|
||||
#![feature(specialization)]
|
||||
//~^ WARN the feature `specialization` is incomplete
|
||||
|
||||
@ -8,6 +7,7 @@ trait Iterate<'a> {
|
||||
}
|
||||
impl<'a, T> Iterate<'a> for T where T: Check {
|
||||
default type Ty = ();
|
||||
//~^ ERROR the trait bound `(): Valid` is not satisfied
|
||||
default fn iterate(self) {}
|
||||
}
|
||||
|
||||
|
@ -7,5 +7,15 @@ LL | #![feature(specialization)]
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
|
||||
warning: 1 warning emitted
|
||||
error[E0277]: the trait bound `(): Valid` is not satisfied
|
||||
--> $DIR/issue-38091.rs:8:5
|
||||
|
|
||||
LL | trait Iterate<'a> {
|
||||
| ----------------- required by `Iterate`
|
||||
...
|
||||
LL | default type Ty = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -0,0 +1,24 @@
|
||||
// Check that we check that default associated types satisfy the required
|
||||
// bounds on them.
|
||||
|
||||
#![feature(specialization)]
|
||||
//~^ WARNING `specialization` is incomplete
|
||||
|
||||
trait X {
|
||||
type U: Clone;
|
||||
fn unsafe_clone(&self, x: Option<&Self::U>) {
|
||||
x.cloned();
|
||||
}
|
||||
}
|
||||
|
||||
// We cannot normalize `<T as X>::U` to `str` here, because the default could
|
||||
// be overridden. The error here must therefore be found by a method other than
|
||||
// normalization.
|
||||
impl<T> X for T {
|
||||
default type U = str;
|
||||
//~^ ERROR the trait bound `str: std::clone::Clone` is not satisfied
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
1.unsafe_clone(None);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/deafult-associated-type-bound-1.rs:4:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
|
||||
error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied
|
||||
--> $DIR/deafult-associated-type-bound-1.rs:18:5
|
||||
|
|
||||
LL | trait X {
|
||||
| ------- required by `X`
|
||||
...
|
||||
LL | default type U = str;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,22 @@
|
||||
// Check that generic predicates are also checked for default associated types.
|
||||
#![feature(specialization)]
|
||||
//~^ WARNING `specialization` is incomplete
|
||||
|
||||
trait X<T> {
|
||||
type U: PartialEq<T>;
|
||||
fn unsafe_compare(x: Option<Self::U>, y: Option<T>) {
|
||||
match (x, y) {
|
||||
(Some(a), Some(b)) => a == b,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: 'static, T> X<B> for T {
|
||||
default type U = &'static B;
|
||||
//~^ ERROR can't compare `&'static B` with `B`
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
<i32 as X<i32>>::unsafe_compare(None, None);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/deafult-associated-type-bound-2.rs:2:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
|
||||
error[E0277]: can't compare `&'static B` with `B`
|
||||
--> $DIR/deafult-associated-type-bound-2.rs:16:5
|
||||
|
|
||||
LL | trait X<T> {
|
||||
| ---------- required by `X`
|
||||
...
|
||||
LL | default type U = &'static B;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B`
|
||||
|
|
||||
= help: the trait `std::cmp::PartialEq<B>` is not implemented for `&'static B`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,27 @@
|
||||
// Check that default generics associated types are validated.
|
||||
|
||||
#![feature(specialization)]
|
||||
#![feature(generic_associated_types)]
|
||||
//~^^ WARNING `specialization` is incomplete
|
||||
//~^^ WARNING the feature `generic_associated_types` is incomplete
|
||||
|
||||
trait X {
|
||||
type U<'a>: PartialEq<&'a Self>;
|
||||
fn unsafe_compare<'b>(x: Option<Self::U<'b>>, y: Option<&'b Self>) {
|
||||
match (x, y) {
|
||||
(Some(a), Some(b)) => a == b,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> X for T {
|
||||
default type U<'a> = &'a T;
|
||||
//~^ ERROR can't compare `T` with `T`
|
||||
}
|
||||
|
||||
struct NotComparable;
|
||||
|
||||
pub fn main() {
|
||||
<NotComparable as X>::unsafe_compare(None, None);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/deafult-generic-associated-type-bound.rs:3:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/deafult-generic-associated-type-bound.rs:4:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: can't compare `T` with `T`
|
||||
--> $DIR/deafult-generic-associated-type-bound.rs:19:5
|
||||
|
|
||||
LL | trait X {
|
||||
| ------- required by `X`
|
||||
...
|
||||
LL | default type U<'a> = &'a T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T == T`
|
||||
|
|
||||
= help: the trait `std::cmp::PartialEq` is not implemented for `T`
|
||||
= note: required because of the requirements on the impl of `for<'a> std::cmp::PartialEq` for `&'a T`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | impl<T: 'static + std::cmp::PartialEq> X for T {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 2 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user