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
21 changed files with 625 additions and 6 deletions
|
@ -4,15 +4,17 @@ use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit;
|
use rustc_hir::intravisit;
|
||||||
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
|
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
|
||||||
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
||||||
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
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::util::ExplicitSelf;
|
||||||
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
|
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
|
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
|
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
|
||||||
|
|
||||||
use super::{potentially_plural_count, FnCtxt, Inherited};
|
use super::{potentially_plural_count, FnCtxt, Inherited};
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
/// Checks that a method from an impl conforms to the signature of
|
/// Checks that a method from an impl conforms to the signature of
|
||||||
/// the same method as declared in the trait.
|
/// the same method as declared in the trait.
|
||||||
|
@ -1057,13 +1059,15 @@ crate fn compare_ty_impl<'tcx>(
|
||||||
let _: Result<(), ErrorReported> = (|| {
|
let _: Result<(), ErrorReported> = (|| {
|
||||||
compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
|
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
|
/// The equivalent of [compare_predicate_entailment], but for associated types
|
||||||
/// instead of associated functions.
|
/// instead of associated functions.
|
||||||
fn compare_type_predicate_entailment(
|
fn compare_type_predicate_entailment<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
impl_ty: &ty::AssocItem,
|
impl_ty: &ty::AssocItem,
|
||||||
impl_ty_span: Span,
|
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 {
|
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
|
||||||
match impl_item.kind {
|
match impl_item.kind {
|
||||||
ty::AssocKind::Const => "const",
|
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)]
|
#![feature(specialization)]
|
||||||
//~^ WARN the feature `specialization` is incomplete
|
//~^ WARN the feature `specialization` is incomplete
|
||||||
|
|
||||||
|
@ -8,6 +7,7 @@ trait Iterate<'a> {
|
||||||
}
|
}
|
||||||
impl<'a, T> Iterate<'a> for T where T: Check {
|
impl<'a, T> Iterate<'a> for T where T: Check {
|
||||||
default type Ty = ();
|
default type Ty = ();
|
||||||
|
//~^ ERROR the trait bound `(): Valid` is not satisfied
|
||||||
default fn iterate(self) {}
|
default fn iterate(self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,5 +7,15 @@ LL | #![feature(specialization)]
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
= 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…
Add table
Add a link
Reference in a new issue