Auto merge of #96899 - oli-obk:closure_wf_check_bounds, r=nikomatsakis
Check that closures satisfy their where bounds fixes https://github.com/rust-lang/rust/issues/53092 fixes https://github.com/rust-lang/rust/issues/90409 based on https://github.com/rust-lang/rust/pull/96736
This commit is contained in:
commit
a7d6408b05
24 changed files with 325 additions and 186 deletions
|
|
@ -1,11 +1,8 @@
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::OpaqueTyOrigin;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::opaque_types::InferCtxtExt;
|
||||
|
||||
use super::RegionInferenceContext;
|
||||
|
|
@ -107,21 +104,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
let opaque_type_key =
|
||||
OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
|
||||
let remapped_type = infcx.infer_opaque_definition_from_instantiation(
|
||||
let ty = infcx.infer_opaque_definition_from_instantiation(
|
||||
opaque_type_key,
|
||||
universal_concrete_type,
|
||||
origin,
|
||||
);
|
||||
let ty = if check_opaque_type_parameter_valid(
|
||||
infcx.tcx,
|
||||
opaque_type_key,
|
||||
origin,
|
||||
concrete_type.span,
|
||||
) {
|
||||
remapped_type
|
||||
} else {
|
||||
infcx.tcx.ty_error()
|
||||
};
|
||||
// Sometimes two opaque types are the same only after we remap the generic parameters
|
||||
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
|
||||
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
|
||||
|
|
@ -184,95 +171,3 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn check_opaque_type_parameter_valid(
|
||||
tcx: TyCtxt<'_>,
|
||||
opaque_type_key: OpaqueTypeKey<'_>,
|
||||
origin: OpaqueTyOrigin,
|
||||
span: Span,
|
||||
) -> bool {
|
||||
match origin {
|
||||
// No need to check return position impl trait (RPIT)
|
||||
// because for type and const parameters they are correct
|
||||
// by construction: we convert
|
||||
//
|
||||
// fn foo<P0..Pn>() -> impl Trait
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type Foo<P0...Pn>
|
||||
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
|
||||
//
|
||||
// For lifetime parameters we convert
|
||||
//
|
||||
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type foo::<'p0..'pn>::Foo<'q0..'qm>
|
||||
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
|
||||
//
|
||||
// which would error here on all of the `'static` args.
|
||||
OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
|
||||
// Check these
|
||||
OpaqueTyOrigin::TyAlias => {}
|
||||
}
|
||||
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
||||
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
|
||||
for (i, arg) in opaque_type_key.substs.iter().enumerate() {
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
||||
GenericArgKind::Lifetime(lt) if lt.is_static() => {
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_label(
|
||||
tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
|
||||
"cannot use static lifetime; use a bound lifetime \
|
||||
instead or remove the lifetime parameter from the \
|
||||
opaque type",
|
||||
)
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
|
||||
}
|
||||
GenericArgKind::Const(ct) => matches!(ct.val(), ty::ConstKind::Param(_)),
|
||||
};
|
||||
|
||||
if arg_is_param {
|
||||
seen_params.entry(arg).or_default().push(i);
|
||||
} else {
|
||||
// Prevent `fn foo() -> Foo<u32>` from being defining.
|
||||
let opaque_param = opaque_generics.param_at(i, tcx);
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(
|
||||
tcx.def_span(opaque_param.def_id),
|
||||
&format!(
|
||||
"used non-generic {} `{}` for generic parameter",
|
||||
opaque_param.kind.descr(),
|
||||
arg,
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (_, indices) in seen_params {
|
||||
if indices.len() > 1 {
|
||||
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
|
||||
let spans: Vec<_> = indices
|
||||
.into_iter()
|
||||
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
|
||||
.collect();
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(spans, &format!("{} used multiple times", descr))
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
));
|
||||
debug!(?definition_ty);
|
||||
|
||||
if !check_opaque_type_parameter_valid(
|
||||
self.tcx,
|
||||
opaque_type_key,
|
||||
origin,
|
||||
instantiated_ty.span,
|
||||
) {
|
||||
return self.tcx.ty_error();
|
||||
}
|
||||
|
||||
// Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs`
|
||||
// on stable and we'd break that.
|
||||
if let OpaqueTyOrigin::TyAlias = origin {
|
||||
|
|
@ -148,6 +157,98 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_opaque_type_parameter_valid(
|
||||
tcx: TyCtxt<'_>,
|
||||
opaque_type_key: OpaqueTypeKey<'_>,
|
||||
origin: OpaqueTyOrigin,
|
||||
span: Span,
|
||||
) -> bool {
|
||||
match origin {
|
||||
// No need to check return position impl trait (RPIT)
|
||||
// because for type and const parameters they are correct
|
||||
// by construction: we convert
|
||||
//
|
||||
// fn foo<P0..Pn>() -> impl Trait
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type Foo<P0...Pn>
|
||||
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
|
||||
//
|
||||
// For lifetime parameters we convert
|
||||
//
|
||||
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type foo::<'p0..'pn>::Foo<'q0..'qm>
|
||||
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
|
||||
//
|
||||
// which would error here on all of the `'static` args.
|
||||
OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
|
||||
// Check these
|
||||
OpaqueTyOrigin::TyAlias => {}
|
||||
}
|
||||
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
||||
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
|
||||
for (i, arg) in opaque_type_key.substs.iter().enumerate() {
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
||||
GenericArgKind::Lifetime(lt) if lt.is_static() => {
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_label(
|
||||
tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
|
||||
"cannot use static lifetime; use a bound lifetime \
|
||||
instead or remove the lifetime parameter from the \
|
||||
opaque type",
|
||||
)
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
|
||||
}
|
||||
GenericArgKind::Const(ct) => matches!(ct.val(), ty::ConstKind::Param(_)),
|
||||
};
|
||||
|
||||
if arg_is_param {
|
||||
seen_params.entry(arg).or_default().push(i);
|
||||
} else {
|
||||
// Prevent `fn foo() -> Foo<u32>` from being defining.
|
||||
let opaque_param = opaque_generics.param_at(i, tcx);
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(
|
||||
tcx.def_span(opaque_param.def_id),
|
||||
&format!(
|
||||
"used non-generic {} `{}` for generic parameter",
|
||||
opaque_param.kind.descr(),
|
||||
arg,
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (_, indices) in seen_params {
|
||||
if indices.len() > 1 {
|
||||
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
|
||||
let spans: Vec<_> = indices
|
||||
.into_iter()
|
||||
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
|
||||
.collect();
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(spans, &format!("{} used multiple times", descr))
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
struct ReverseMapper<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
||||
|
|
|
|||
|
|
@ -575,7 +575,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
// generators don't take arguments.
|
||||
}
|
||||
|
||||
ty::Closure(_, substs) => {
|
||||
ty::Closure(did, substs) => {
|
||||
// Only check the upvar types for WF, not the rest
|
||||
// of the types within. This is needed because we
|
||||
// capture the signature and it may not be WF
|
||||
|
|
@ -596,18 +596,26 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
// probably always be WF, because it should be
|
||||
// shorthand for something like `where(T: 'a) {
|
||||
// fn(&'a T) }`, as discussed in #25860.
|
||||
//
|
||||
// Note that we are also skipping the generic
|
||||
// types. This is consistent with the `outlives`
|
||||
// code, but anyway doesn't matter: within the fn
|
||||
walker.skip_current_subtree(); // subtree handled below
|
||||
// FIXME(eddyb) add the type to `walker` instead of recursing.
|
||||
self.compute(substs.as_closure().tupled_upvars_ty().into());
|
||||
// Note that we cannot skip the generic types
|
||||
// types. Normally, within the fn
|
||||
// body where they are created, the generics will
|
||||
// always be WF, and outside of that fn body we
|
||||
// are not directly inspecting closure types
|
||||
// anyway, except via auto trait matching (which
|
||||
// only inspects the upvar types).
|
||||
walker.skip_current_subtree(); // subtree handled below
|
||||
// FIXME(eddyb) add the type to `walker` instead of recursing.
|
||||
self.compute(substs.as_closure().tupled_upvars_ty().into());
|
||||
// But when a closure is part of a type-alias-impl-trait
|
||||
// then the function that created the defining site may
|
||||
// have had more bounds available than the type alias
|
||||
// specifies. This may cause us to have a closure in the
|
||||
// hidden type that is not actually well formed and
|
||||
// can cause compiler crashes when the user abuses unsafe
|
||||
// code to procure such a closure.
|
||||
// See src/test/ui/type-alias-impl-trait/wf_check_closures.rs
|
||||
let obligations = self.nominal_obligations(did, substs);
|
||||
self.out.extend(obligations);
|
||||
}
|
||||
|
||||
ty::FnPtr(_) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
|
||||
//~^ ERROR overly complex generic constant
|
||||
//~^ ERROR cycle detected when building an abstract representation
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,26 @@
|
|||
error: overly complex generic constant
|
||||
error[E0391]: cycle detected when building an abstract representation for test::{constant#0}
|
||||
--> $DIR/closures.rs:3:35
|
||||
|
|
||||
LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
|
||||
| ^^^^-------^^
|
||||
| |
|
||||
| borrowing is not supported in generic constants
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider moving this anonymous constant into a `const` function
|
||||
= note: this operation may be supported in the future
|
||||
note: ...which requires building THIR for `test::{constant#0}`...
|
||||
--> $DIR/closures.rs:3:35
|
||||
|
|
||||
LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires type-checking `test::{constant#0}`...
|
||||
--> $DIR/closures.rs:3:35
|
||||
|
|
||||
LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: ...which again requires building an abstract representation for test::{constant#0}, completing the cycle
|
||||
note: cycle used when checking that `test` is well-formed
|
||||
--> $DIR/closures.rs:3:1
|
||||
|
|
||||
LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
|
|
|||
18
src/test/ui/higher-rank-trait-bounds/issue-59311.nll.stderr
Normal file
18
src/test/ui/higher-rank-trait-bounds/issue-59311.nll.stderr
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
error: higher-ranked lifetime error
|
||||
--> $DIR/issue-59311.rs:17:5
|
||||
|
|
||||
LL | v.t(|| {});
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: could not prove [closure@$DIR/issue-59311.rs:17:9: 17:14] well-formed
|
||||
|
||||
error: higher-ranked lifetime error
|
||||
--> $DIR/issue-59311.rs:17:9
|
||||
|
|
||||
LL | v.t(|| {});
|
||||
| ^^^^^
|
||||
|
|
||||
= note: could not prove for<'a> &'a V: 'static
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ pub fn crash<V>(v: &V)
|
|||
where
|
||||
for<'a> &'a V: T + 'static,
|
||||
{
|
||||
v.t(|| {}); //~ ERROR: higher-ranked lifetime error
|
||||
v.t(|| {}); //~ ERROR: `&'a V` does not fulfill the required lifetime
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
error: higher-ranked lifetime error
|
||||
--> $DIR/issue-59311.rs:17:9
|
||||
error[E0477]: the type `&'a V` does not fulfill the required lifetime
|
||||
--> $DIR/issue-59311.rs:17:5
|
||||
|
|
||||
LL | v.t(|| {});
|
||||
| ^^^^^
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: could not prove for<'a> &'a V: 'static
|
||||
note: type must satisfy the static lifetime as required by this binding
|
||||
--> $DIR/issue-59311.rs:15:24
|
||||
|
|
||||
LL | for<'a> &'a V: T + 'static,
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0477`.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ type TwoConsts<const X: usize, const Y: usize> = impl Debug;
|
|||
fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
|
||||
t
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR `U` doesn't implement `Debug`
|
||||
}
|
||||
|
||||
fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,3 @@
|
|||
error[E0277]: `U` doesn't implement `Debug`
|
||||
--> $DIR/generic_duplicate_param_use.rs:16:5
|
||||
|
|
||||
LL | t
|
||||
| ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
||||
|
|
||||
help: consider restricting type parameter `U`
|
||||
|
|
||||
LL | type TwoTys<T, U: std::fmt::Debug> = impl Debug;
|
||||
| +++++++++++++++++
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.rs:16:5
|
||||
|
|
||||
|
|
@ -22,7 +11,7 @@ LL | type TwoTys<T, U> = impl Debug;
|
|||
| ^ ^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.rs:22:5
|
||||
--> $DIR/generic_duplicate_param_use.rs:21:5
|
||||
|
|
||||
LL | t
|
||||
| ^
|
||||
|
|
@ -34,7 +23,7 @@ LL | type TwoLifetimes<'a, 'b> = impl Debug;
|
|||
| ^^ ^^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.rs:27:5
|
||||
--> $DIR/generic_duplicate_param_use.rs:26:5
|
||||
|
|
||||
LL | t
|
||||
| ^
|
||||
|
|
@ -45,6 +34,5 @@ note: constant used multiple times
|
|||
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
|
||||
| ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
14
src/test/ui/type-alias-impl-trait/issue-53092.rs
Normal file
14
src/test/ui/type-alias-impl-trait/issue-53092.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||
|
||||
const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
|
||||
fn make_bug<T, U: From<T>>() -> Bug<T, U> {
|
||||
|x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {
|
||||
CONST_BUG(0);
|
||||
}
|
||||
19
src/test/ui/type-alias-impl-trait/issue-53092.stderr
Normal file
19
src/test/ui/type-alias-impl-trait/issue-53092.stderr
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
error[E0277]: the trait bound `U: From<T>` is not satisfied
|
||||
--> $DIR/issue-53092.rs:9:5
|
||||
|
|
||||
LL | |x| x.into()
|
||||
| ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
|
||||
|
|
||||
note: required by a bound in `make_bug`
|
||||
--> $DIR/issue-53092.rs:8:19
|
||||
|
|
||||
LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
|
||||
| ^^^^^^^ required by this bound in `make_bug`
|
||||
help: consider restricting type parameter `U`
|
||||
|
|
||||
LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
|
||||
| +++++++++++++++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
24
src/test/ui/type-alias-impl-trait/issue-60564-working.rs
Normal file
24
src/test/ui/type-alias-impl-trait/issue-60564-working.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
// check-pass
|
||||
|
||||
trait IterBits {
|
||||
type BitsIter: Iterator<Item = u8>;
|
||||
fn iter_bits(self, n: u8) -> Self::BitsIter;
|
||||
}
|
||||
|
||||
impl<T: Copy, E> IterBits for T
|
||||
where
|
||||
T: std::ops::Shr<Output = T>
|
||||
+ std::ops::BitAnd<T, Output = T>
|
||||
+ std::convert::From<u8>
|
||||
+ std::convert::TryInto<u8, Error = E>,
|
||||
E: std::fmt::Debug,
|
||||
{
|
||||
type BitsIter = impl std::iter::Iterator<Item = u8>;
|
||||
fn iter_bits(self, n: u8) -> Self::BitsIter {
|
||||
(0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -19,7 +19,6 @@ where
|
|||
fn iter_bits(self, n: u8) -> Self::BitsIter {
|
||||
(0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR type mismatch resolving
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,3 @@
|
|||
error[E0271]: type mismatch resolving `<[closure@$DIR/issue-60564.rs:20:28: 20:100] as FnOnce<(u8,)>>::Output == I`
|
||||
--> $DIR/issue-60564.rs:20:9
|
||||
|
|
||||
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
|
||||
| - this type parameter
|
||||
...
|
||||
LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found type parameter `I`
|
||||
|
|
||||
= note: expected type `u8`
|
||||
found type parameter `I`
|
||||
= note: required because of the requirements on the impl of `Iterator` for `Map<Rev<std::ops::Range<u8>>, [closure@$DIR/issue-60564.rs:20:28: 20:100]>`
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-60564.rs:20:9
|
||||
|
|
||||
|
|
@ -23,6 +10,5 @@ note: used non-generic type `u8` for generic parameter
|
|||
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ type Alias<'a, U> = impl Trait<U>;
|
|||
|
||||
fn f<'a>() -> Alias<'a, ()> {}
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR the trait bound `(): Trait<U>` is not satisfied
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,3 @@
|
|||
error[E0277]: the trait bound `(): Trait<U>` is not satisfied
|
||||
--> $DIR/issue-68368-non-defining-use.rs:9:29
|
||||
|
|
||||
LL | fn f<'a>() -> Alias<'a, ()> {}
|
||||
| ^^ the trait `Trait<U>` is not implemented for `()`
|
||||
|
|
||||
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | type Alias<'a, U> = impl Trait<U> where (): Trait<U>;
|
||||
| ++++++++++++++++++
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-68368-non-defining-use.rs:9:29
|
||||
|
|
||||
|
|
@ -21,6 +10,5 @@ note: used non-generic type `()` for generic parameter
|
|||
LL | type Alias<'a, U> = impl Trait<U>;
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,5 @@ type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
|
|||
|
||||
fn my_fun() -> Return<()> {}
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR non-defining opaque type use in defining scope
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -26,18 +26,6 @@ note: used non-generic type `()` for generic parameter
|
|||
LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
|
||||
| ^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27
|
||||
|
|
||||
LL | fn my_fun() -> Return<()> {}
|
||||
| ^^
|
||||
|
|
||||
note: used non-generic type `()` for generic parameter
|
||||
--> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13
|
||||
|
|
||||
LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
|
||||
| ^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0261`.
|
||||
|
|
|
|||
18
src/test/ui/type-alias-impl-trait/wf-check-fn-def.rs
Normal file
18
src/test/ui/type-alias-impl-trait/wf-check-fn-def.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Bar {
|
||||
fn bar(&self);
|
||||
}
|
||||
|
||||
type FooFn<B> = impl FnOnce(B);
|
||||
|
||||
fn foo<B: Bar>() -> FooFn<B> {
|
||||
fn mop<B: Bar>(bar: B) { bar.bar() }
|
||||
mop // NOTE: no function pointer, but function zst item
|
||||
//~^ ERROR the trait bound `B: Bar` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let boom: FooFn<u32> = unsafe { core::mem::zeroed() };
|
||||
boom(42);
|
||||
}
|
||||
19
src/test/ui/type-alias-impl-trait/wf-check-fn-def.stderr
Normal file
19
src/test/ui/type-alias-impl-trait/wf-check-fn-def.stderr
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
error[E0277]: the trait bound `B: Bar` is not satisfied
|
||||
--> $DIR/wf-check-fn-def.rs:11:5
|
||||
|
|
||||
LL | mop // NOTE: no function pointer, but function zst item
|
||||
| ^^^ the trait `Bar` is not implemented for `B`
|
||||
|
|
||||
note: required by a bound in `mop`
|
||||
--> $DIR/wf-check-fn-def.rs:10:15
|
||||
|
|
||||
LL | fn mop<B: Bar>(bar: B) { bar.bar() }
|
||||
| ^^^ required by this bound in `mop`
|
||||
help: consider restricting type parameter `B`
|
||||
|
|
||||
LL | type FooFn<B: Bar> = impl FnOnce(B);
|
||||
| +++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
23
src/test/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs
Normal file
23
src/test/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
// build-pass
|
||||
|
||||
trait Bar {
|
||||
fn bar(&self);
|
||||
}
|
||||
|
||||
type FooFn<B> = impl FnOnce(B);
|
||||
|
||||
fn foo<B: Bar>() -> FooFn<B> {
|
||||
fn mop<B: Bar>(bar: B) { bar.bar() }
|
||||
mop as fn(B)
|
||||
// function pointers don't have any obligations on them,
|
||||
// thus the above compiles. It's obviously unsound to just
|
||||
// procure a `FooFn` from the ether without making sure that
|
||||
// the pointer is actually legal for all `B`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let boom: FooFn<u32> = unsafe { core::mem::zeroed() };
|
||||
boom(42);
|
||||
}
|
||||
17
src/test/ui/type-alias-impl-trait/wf_check_closures.rs
Normal file
17
src/test/ui/type-alias-impl-trait/wf_check_closures.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Bar {
|
||||
fn bar(&self);
|
||||
}
|
||||
|
||||
type FooFn<B> = impl FnOnce();
|
||||
|
||||
fn foo<B: Bar>(bar: B) -> FooFn<B> {
|
||||
move || { bar.bar() }
|
||||
//~^ ERROR the trait bound `B: Bar` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let boom: FooFn<u32> = unsafe { core::mem::zeroed() };
|
||||
boom();
|
||||
}
|
||||
19
src/test/ui/type-alias-impl-trait/wf_check_closures.stderr
Normal file
19
src/test/ui/type-alias-impl-trait/wf_check_closures.stderr
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
error[E0277]: the trait bound `B: Bar` is not satisfied
|
||||
--> $DIR/wf_check_closures.rs:10:5
|
||||
|
|
||||
LL | move || { bar.bar() }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B`
|
||||
|
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/wf_check_closures.rs:9:11
|
||||
|
|
||||
LL | fn foo<B: Bar>(bar: B) -> FooFn<B> {
|
||||
| ^^^ required by this bound in `foo`
|
||||
help: consider restricting type parameter `B`
|
||||
|
|
||||
LL | type FooFn<B: Bar> = impl FnOnce();
|
||||
| +++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue