mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #70272 - eddyb:type-of-impl-trait, r=nikomatsakis
typeck/type_of: let wfcheck handle generics in opaque types' substs. I was working on #70164, and `type_of`'s handling of opaque types seemed to be, by far, the trickiest use of `Ty::walk`, but I believe it wasn't doing anything (see https://github.com/rust-lang/rust/pull/57896#discussion_r396064431 - I suspect, based on glancing at the PR discussion, that an early attempt was kept in, despite becoming just an overcomplicated way to do exactly the same as the previous simple type equality check). I would've loved to remove `ResolvedOpaqueTy` (keep the `Ty` and lose the `Substs`), but it looks like the MIR borrowck part of the process needs that now, so it would've been added anyway since #57896, even if that PR hadn't happened. <hr/> In the process, I've moved the remaining substitution validation to `wfcheck`, which was already handling lifetimes, and kept only `delay_span_bug`s in `type_of`, as an insurance policy. I've added tests for lifetime and const cases, they seem to be checked correctly now. (and more uniform than they were in https://github.com/rust-lang/rust/issues/63063#issuecomment-602162804) However, the quality of the errors is maybe a bit worse, and they don't trigger when there are other errors (not sure if this is due to compilation stop points or something more specific to one opaque type). r? @nikomatsakis cc @matthewjasper @oli-obk @Aaron1011
This commit is contained in:
commit
49dc2f9f09
@ -1077,48 +1077,42 @@ impl<'tcx> Generics {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
|
||||
if let Some(index) = param_index.checked_sub(self.parent_count) {
|
||||
&self.params[index]
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
|
||||
.param_at(param_index, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn region_param(
|
||||
&'tcx self,
|
||||
param: &EarlyBoundRegion,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> &'tcx GenericParamDef {
|
||||
if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
|
||||
let param = &self.params[index as usize];
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => param,
|
||||
_ => bug!("expected lifetime parameter, but found another generic parameter"),
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
|
||||
.region_param(param, tcx)
|
||||
let param = self.param_at(param.index as usize, tcx);
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => param,
|
||||
_ => bug!("expected lifetime parameter, but found another generic parameter"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `GenericParamDef` associated with this `ParamTy`.
|
||||
pub fn type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
|
||||
if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
|
||||
let param = &self.params[index as usize];
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type { .. } => param,
|
||||
_ => bug!("expected type parameter, but found another generic parameter"),
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
|
||||
.type_param(param, tcx)
|
||||
let param = self.param_at(param.index as usize, tcx);
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type { .. } => param,
|
||||
_ => bug!("expected type parameter, but found another generic parameter"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `ConstParameterDef` associated with this `ParamConst`.
|
||||
pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef {
|
||||
if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
|
||||
let param = &self.params[index as usize];
|
||||
match param.kind {
|
||||
GenericParamDefKind::Const => param,
|
||||
_ => bug!("expected const parameter, but found another generic parameter"),
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
|
||||
.const_param(param, tcx)
|
||||
let param = self.param_at(param.index as usize, tcx);
|
||||
match param.kind {
|
||||
GenericParamDefKind::Const => param,
|
||||
_ => bug!("expected const parameter, but found another generic parameter"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::itemlikevisit::ParItemLikeVisitor;
|
||||
use rustc_hir::lang_items;
|
||||
use rustc_hir::ItemKind;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
|
||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
|
||||
@ -864,87 +864,77 @@ fn check_opaque_types<'fcx, 'tcx>(
|
||||
trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
|
||||
let generics = tcx.generics_of(def_id);
|
||||
// Only check named `impl Trait` types defined in this crate.
|
||||
// FIXME(eddyb) is `generics.parent.is_none()` correct? It seems
|
||||
// potentially risky wrt associated types in `impl`s.
|
||||
if generics.parent.is_none() && def_id.is_local() {
|
||||
let opaque_hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
|
||||
if may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
|
||||
trace!("check_opaque_types: may define, generics={:#?}", generics);
|
||||
let mut seen: FxHashMap<_, Vec<_>> = FxHashMap::default();
|
||||
for (subst, param) in substs.iter().zip(&generics.params) {
|
||||
match subst.unpack() {
|
||||
ty::subst::GenericArgKind::Type(ty) => match ty.kind {
|
||||
ty::Param(..) => {}
|
||||
// Prevent `fn foo() -> Foo<u32>` from being defining.
|
||||
_ => {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
span,
|
||||
"non-defining opaque type use \
|
||||
in defining scope",
|
||||
)
|
||||
.span_note(
|
||||
tcx.def_span(param.def_id),
|
||||
&format!(
|
||||
"used non-generic type {} for \
|
||||
generic parameter",
|
||||
ty,
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
},
|
||||
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
|
||||
for (i, &arg) in substs.iter().enumerate() {
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
|
||||
|
||||
ty::subst::GenericArgKind::Lifetime(region) => {
|
||||
let param_span = tcx.def_span(param.def_id);
|
||||
GenericArgKind::Lifetime(region) => {
|
||||
if let ty::ReStatic = region {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
span,
|
||||
"non-defining opaque type use \
|
||||
in defining scope",
|
||||
"non-defining opaque type use in defining scope",
|
||||
)
|
||||
.span_label(
|
||||
param_span,
|
||||
tcx.def_span(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();
|
||||
} else {
|
||||
seen.entry(region).or_default().push(param_span);
|
||||
continue;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
ty::subst::GenericArgKind::Const(ct) => match ct.val {
|
||||
ty::ConstKind::Param(_) => {}
|
||||
_ => {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
span,
|
||||
"non-defining opaque type use \
|
||||
in defining scope",
|
||||
)
|
||||
.span_note(
|
||||
tcx.def_span(param.def_id),
|
||||
&format!(
|
||||
"used non-generic const {} for \
|
||||
generic parameter",
|
||||
ty,
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
},
|
||||
} // match subst
|
||||
} // for (subst, param)
|
||||
for (_, spans) in seen {
|
||||
if spans.len() > 1 {
|
||||
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 = generics.param_at(i, tcx);
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
span,
|
||||
"non-defining opaque type use \
|
||||
in defining scope",
|
||||
"non-defining opaque type use in defining scope",
|
||||
)
|
||||
.span_note(spans, "lifetime used multiple times")
|
||||
.span_note(
|
||||
tcx.def_span(opaque_param.def_id),
|
||||
&format!(
|
||||
"used non-generic {} `{}` for generic parameter",
|
||||
opaque_param.kind.descr(),
|
||||
arg,
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
} // for (arg, param)
|
||||
|
||||
for (_, indices) in seen_params {
|
||||
if indices.len() > 1 {
|
||||
let descr = generics.param_at(indices[0], tcx).kind.descr();
|
||||
let spans: Vec<_> = indices
|
||||
.into_iter()
|
||||
.map(|i| tcx.def_span(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();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{struct_span_err, Applicability, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
@ -7,7 +7,7 @@ use rustc_hir::intravisit;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::Node;
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
|
||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_session::parse::feature_err;
|
||||
@ -369,13 +369,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
struct ConstraintLocator<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
// (first found type span, actual type, mapping from the opaque type's generic
|
||||
// parameters to the concrete type's generic parameters)
|
||||
//
|
||||
// The mapping is an index for each use site of a generic parameter in the concrete type
|
||||
//
|
||||
// The indices index into the generic parameters on the opaque type.
|
||||
found: Option<(Span, Ty<'tcx>, Vec<usize>)>,
|
||||
// (first found type span, actual type)
|
||||
found: Option<(Span, Ty<'tcx>)>,
|
||||
}
|
||||
|
||||
impl ConstraintLocator<'_> {
|
||||
@ -407,83 +402,51 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
|
||||
// FIXME(oli-obk): trace the actual span from inference to improve errors.
|
||||
let span = self.tcx.def_span(def_id);
|
||||
// used to quickly look up the position of a generic parameter
|
||||
let mut index_map: FxHashMap<ty::ParamTy, usize> = FxHashMap::default();
|
||||
// Skipping binder is ok, since we only use this to find generic parameters and
|
||||
// their positions.
|
||||
for (idx, subst) in substs.iter().enumerate() {
|
||||
if let GenericArgKind::Type(ty) = subst.unpack() {
|
||||
if let ty::Param(p) = ty.kind {
|
||||
if index_map.insert(p, idx).is_some() {
|
||||
// There was already an entry for `p`, meaning a generic parameter
|
||||
// was used twice.
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
&format!(
|
||||
"defining opaque type use restricts opaque \
|
||||
type by using the generic parameter `{}` twice",
|
||||
p,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
// HACK(eddyb) this check shouldn't be needed, as `wfcheck`
|
||||
// performs the same checks, in theory, but I've kept it here
|
||||
// using `delay_span_bug`, just in case `wfcheck` slips up.
|
||||
let opaque_generics = self.tcx.generics_of(self.def_id);
|
||||
let mut used_params: FxHashSet<_> = FxHashSet::default();
|
||||
for (i, arg) in substs.iter().enumerate() {
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
|
||||
}
|
||||
GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
|
||||
};
|
||||
|
||||
if arg_is_param {
|
||||
if !used_params.insert(arg) {
|
||||
// There was already an entry for `arg`, meaning a generic parameter
|
||||
// was used twice.
|
||||
self.tcx.sess.delay_span_bug(
|
||||
span,
|
||||
&format!(
|
||||
"non-defining opaque ty use in defining scope: {:?}, {:?}",
|
||||
concrete_type, substs,
|
||||
"defining opaque type use restricts opaque \
|
||||
type by using the generic parameter `{}` twice",
|
||||
arg,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compute the index within the opaque type for each generic parameter used in
|
||||
// the concrete type.
|
||||
let indices = concrete_type
|
||||
.subst(self.tcx, substs)
|
||||
.walk()
|
||||
.filter_map(|t| match &t.kind {
|
||||
ty::Param(p) => Some(*index_map.get(p).unwrap()),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
let is_param = |ty: Ty<'_>| match ty.kind {
|
||||
ty::Param(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
let bad_substs: Vec<_> = substs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, k)| {
|
||||
if let GenericArgKind::Type(ty) = k.unpack() { Some((i, ty)) } else { None }
|
||||
})
|
||||
.filter(|(_, ty)| !is_param(ty))
|
||||
.collect();
|
||||
if !bad_substs.is_empty() {
|
||||
let identity_substs = InternalSubsts::identity_for_item(self.tcx, self.def_id);
|
||||
for (i, bad_subst) in bad_substs {
|
||||
self.tcx.sess.span_err(
|
||||
} else {
|
||||
let param = opaque_generics.param_at(i, self.tcx);
|
||||
self.tcx.sess.delay_span_bug(
|
||||
span,
|
||||
&format!(
|
||||
"defining opaque type use does not fully define opaque type: \
|
||||
generic parameter `{}` is specified as concrete type `{}`",
|
||||
identity_substs.type_at(i),
|
||||
bad_subst
|
||||
generic parameter `{}` is specified as concrete {} `{}`",
|
||||
param.name,
|
||||
param.kind.descr(),
|
||||
arg,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found {
|
||||
let mut ty = concrete_type.walk().fuse();
|
||||
let mut p_ty = prev_ty.walk().fuse();
|
||||
let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) {
|
||||
// Type parameters are equal to any other type parameter for the purpose of
|
||||
// concrete type equality, as it is possible to obtain the same type just
|
||||
// by passing matching parameters to a function.
|
||||
(ty::Param(_), ty::Param(_)) => true,
|
||||
_ => t == p,
|
||||
});
|
||||
if !iter_eq || ty.next().is_some() || p_ty.next().is_some() {
|
||||
}
|
||||
|
||||
if let Some((prev_span, prev_ty)) = self.found {
|
||||
if *concrete_type != prev_ty {
|
||||
debug!("find_opaque_ty_constraints: span={:?}", span);
|
||||
// Found different concrete types for the opaque type.
|
||||
let mut err = self.tcx.sess.struct_span_err(
|
||||
@ -496,34 +459,9 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
);
|
||||
err.span_note(prev_span, "previous use here");
|
||||
err.emit();
|
||||
} else if indices != *prev_indices {
|
||||
// Found "same" concrete types, but the generic parameter order differs.
|
||||
let mut err = self.tcx.sess.struct_span_err(
|
||||
span,
|
||||
"concrete type's generic parameters differ from previous defining use",
|
||||
);
|
||||
use std::fmt::Write;
|
||||
let mut s = String::new();
|
||||
write!(s, "expected [").unwrap();
|
||||
let list = |s: &mut String, indices: &Vec<usize>| {
|
||||
let mut indices = indices.iter().cloned();
|
||||
if let Some(first) = indices.next() {
|
||||
write!(s, "`{}`", substs[first]).unwrap();
|
||||
for i in indices {
|
||||
write!(s, ", `{}`", substs[i]).unwrap();
|
||||
}
|
||||
}
|
||||
};
|
||||
list(&mut s, prev_indices);
|
||||
write!(s, "], got [").unwrap();
|
||||
list(&mut s, &indices);
|
||||
write!(s, "]").unwrap();
|
||||
err.span_label(span, s);
|
||||
err.span_note(prev_span, "previous use here");
|
||||
err.emit();
|
||||
}
|
||||
} else {
|
||||
self.found = Some((span, concrete_type, indices));
|
||||
self.found = Some((span, concrete_type));
|
||||
}
|
||||
} else {
|
||||
debug!(
|
||||
@ -606,7 +544,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
}
|
||||
|
||||
match locator.found {
|
||||
Some((_, ty, _)) => ty,
|
||||
Some((_, ty)) => ty,
|
||||
None => {
|
||||
let span = tcx.def_span(def_id);
|
||||
tcx.sess.span_err(span, "could not find defining uses");
|
||||
|
@ -8,13 +8,12 @@ trait TraitWithAssoc {
|
||||
}
|
||||
|
||||
type Foo<V> = impl Trait<V>;
|
||||
//~^ ERROR could not find defining uses
|
||||
//~| ERROR the trait bound `T: TraitWithAssoc` is not satisfied
|
||||
//~^ ERROR the trait bound `T: TraitWithAssoc` is not satisfied
|
||||
|
||||
trait Trait<U> {}
|
||||
|
||||
impl<W> Trait<W> for () {}
|
||||
|
||||
fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR does not fully define
|
||||
fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
()
|
||||
}
|
||||
|
@ -9,20 +9,6 @@ help: consider further restricting this bound
|
||||
LL | fn foo_desugared<T: TraitWithAssoc + TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: defining opaque type use does not fully define opaque type: generic parameter `V` is specified as concrete type `<T as TraitWithAssoc>::Assoc`
|
||||
--> $DIR/bound_reduction2.rs:18:1
|
||||
|
|
||||
LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
LL | | ()
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/bound_reduction2.rs:10:1
|
||||
|
|
||||
LL | type Foo<V> = impl Trait<V>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -1,14 +1,26 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(type_alias_impl_trait, const_generics)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn main() {}
|
||||
|
||||
// test that unused generic parameters are ok
|
||||
type Two<T, U> = impl Debug;
|
||||
//~^ could not find defining uses
|
||||
type TwoTys<T, U> = impl Debug;
|
||||
type TwoLifetimes<'a, 'b> = impl Debug;
|
||||
type TwoConsts<const X: usize, const Y: usize> = impl Debug;
|
||||
|
||||
fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
//~^ ERROR defining opaque type use restricts opaque type
|
||||
fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
t
|
||||
}
|
||||
|
||||
fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
t
|
||||
}
|
||||
|
||||
fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
t
|
||||
}
|
||||
|
@ -1,17 +1,38 @@
|
||||
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
|
||||
--> $DIR/generic_duplicate_param_use.rs:11:1
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.rs:13:30
|
||||
|
|
||||
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
LL | |
|
||||
LL | | t
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/generic_duplicate_param_use.rs:8:1
|
||||
LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: type used multiple times
|
||||
--> $DIR/generic_duplicate_param_use.rs:9:13
|
||||
|
|
||||
LL | type TwoTys<T, U> = impl Debug;
|
||||
| ^ ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.rs:18:36
|
||||
|
|
||||
LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime used multiple times
|
||||
--> $DIR/generic_duplicate_param_use.rs:10:19
|
||||
|
|
||||
LL | type TwoLifetimes<'a, 'b> = impl Debug;
|
||||
| ^^ ^^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.rs:23:50
|
||||
|
|
||||
LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: constant used multiple times
|
||||
--> $DIR/generic_duplicate_param_use.rs:11:22
|
||||
|
|
||||
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
|
||||
| ^ ^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -8,10 +8,10 @@ fn main() {}
|
||||
type Two<T, U> = impl Debug;
|
||||
|
||||
fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
//~^ defining opaque type use restricts opaque type
|
||||
t
|
||||
}
|
||||
|
||||
fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||
t
|
||||
}
|
||||
|
@ -1,8 +1,16 @@
|
||||
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/generic_duplicate_param_use2.rs:14:1
|
||||
|
|
||||
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||
LL | |
|
||||
LL | | t
|
||||
LL | | }
|
||||
| |_^ expected `U`, got `T`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/generic_duplicate_param_use2.rs:10:1
|
||||
|
|
||||
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
LL | |
|
||||
LL | | t
|
||||
LL | | }
|
||||
| |_^
|
||||
|
@ -8,15 +8,14 @@ fn main() {}
|
||||
type Two<T, U> = impl Debug;
|
||||
|
||||
fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
//~^ defining opaque type use restricts opaque type
|
||||
t
|
||||
}
|
||||
|
||||
fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||
t
|
||||
}
|
||||
|
||||
fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
|
||||
//~^ concrete type's generic parameters differ from previous defining use
|
||||
u
|
||||
}
|
||||
|
@ -1,28 +1,19 @@
|
||||
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/generic_duplicate_param_use3.rs:14:1
|
||||
|
|
||||
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||
LL | |
|
||||
LL | | t
|
||||
LL | | }
|
||||
| |_^ expected `U`, got `T`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/generic_duplicate_param_use3.rs:10:1
|
||||
|
|
||||
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
LL | |
|
||||
LL | | t
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: concrete type's generic parameters differ from previous defining use
|
||||
--> $DIR/generic_duplicate_param_use3.rs:19:1
|
||||
|
|
||||
LL | / fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
|
||||
LL | |
|
||||
LL | | u
|
||||
LL | | }
|
||||
| |_^ expected [`T`], got [`U`]
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/generic_duplicate_param_use3.rs:15:1
|
||||
|
|
||||
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||
LL | | t
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,7 +8,7 @@ fn main() {}
|
||||
type Two<T, U> = impl Debug;
|
||||
|
||||
fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
//~^ ERROR defining opaque type use restricts opaque type
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
t
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
|
||||
--> $DIR/generic_duplicate_param_use4.rs:10:1
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use4.rs:10:27
|
||||
|
|
||||
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
LL | |
|
||||
LL | | t
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: type used multiple times
|
||||
--> $DIR/generic_duplicate_param_use4.rs:8:10
|
||||
|
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,13 +1,27 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(type_alias_impl_trait, const_generics)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn main() {}
|
||||
|
||||
type Cmp<T> = impl 'static;
|
||||
//~^ ERROR could not find defining uses
|
||||
//~^^ ERROR: at least one trait must be specified
|
||||
type OneTy<T> = impl Debug;
|
||||
type OneLifetime<'a> = impl Debug;
|
||||
type OneConst<const X: usize> = impl Debug;
|
||||
|
||||
// Not defining uses, because they doesn't define *all* possible generics.
|
||||
|
||||
// not a defining use, because it doesn't define *all* possible generics
|
||||
fn cmp() -> Cmp<u32> { //~ ERROR defining opaque type use does not fully define
|
||||
fn concrete_ty() -> OneTy<u32> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
5u32
|
||||
}
|
||||
|
||||
fn concrete_lifetime() -> OneLifetime<'static> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
6u32
|
||||
}
|
||||
|
||||
fn concrete_const() -> OneConst<{123}> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
7u32
|
||||
}
|
||||
|
@ -1,22 +1,35 @@
|
||||
error: at least one trait must be specified
|
||||
--> $DIR/generic_nondefining_use.rs:5:15
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_nondefining_use.rs:14:21
|
||||
|
|
||||
LL | type Cmp<T> = impl 'static;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | fn concrete_ty() -> OneTy<u32> {
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `u32` for generic parameter
|
||||
--> $DIR/generic_nondefining_use.rs:8:12
|
||||
|
|
||||
LL | type OneTy<T> = impl Debug;
|
||||
| ^
|
||||
|
||||
error: defining opaque type use does not fully define opaque type: generic parameter `T` is specified as concrete type `u32`
|
||||
--> $DIR/generic_nondefining_use.rs:11:1
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_nondefining_use.rs:19:27
|
||||
|
|
||||
LL | / fn cmp() -> Cmp<u32> {
|
||||
LL | | 5u32
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | type OneLifetime<'a> = impl Debug;
|
||||
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
||||
...
|
||||
LL | fn concrete_lifetime() -> OneLifetime<'static> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/generic_nondefining_use.rs:5:1
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_nondefining_use.rs:24:24
|
||||
|
|
||||
LL | type Cmp<T> = impl 'static;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | fn concrete_const() -> OneConst<{123}> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic constant `123usize` for generic parameter
|
||||
--> $DIR/generic_nondefining_use.rs:10:21
|
||||
|
|
||||
LL | type OneConst<const X: usize> = impl Debug;
|
||||
| ^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -6,7 +6,6 @@ trait IterBits {
|
||||
}
|
||||
|
||||
type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
|
||||
//~^ ERROR could not find defining uses
|
||||
|
||||
impl<T: Copy, E> IterBits for T
|
||||
where
|
||||
@ -18,7 +17,8 @@ where
|
||||
{
|
||||
type BitsIter = IterBitsIter<T, E, u8>;
|
||||
fn iter_bits(self, n: u8) -> Self::BitsIter {
|
||||
//~^ ERROR defining opaque type use does not fully define opaque type
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR non-defining opaque type use in defining scope
|
||||
(0u8..n)
|
||||
.rev()
|
||||
.map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
|
||||
|
@ -1,19 +1,26 @@
|
||||
error: defining opaque type use does not fully define opaque type: generic parameter `I` is specified as concrete type `u8`
|
||||
--> $DIR/issue-60564.rs:20:5
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-60564.rs:19:34
|
||||
|
|
||||
LL | / fn iter_bits(self, n: u8) -> Self::BitsIter {
|
||||
LL | |
|
||||
LL | | (0u8..n)
|
||||
LL | | .rev()
|
||||
LL | | .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/issue-60564.rs:8:1
|
||||
LL | fn iter_bits(self, n: u8) -> Self::BitsIter {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `_` for generic parameter
|
||||
--> $DIR/issue-60564.rs:8:22
|
||||
|
|
||||
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-60564.rs:19:34
|
||||
|
|
||||
LL | fn iter_bits(self, n: u8) -> Self::BitsIter {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `u8` for generic parameter
|
||||
--> $DIR/issue-60564.rs:8:25
|
||||
|
|
||||
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
trait Trait<T> {}
|
||||
type Alias<'a, U> = impl Trait<U>; //~ ERROR could not find defining uses
|
||||
type Alias<'a, U> = impl Trait<U>;
|
||||
fn f<'a>() -> Alias<'a, ()> {}
|
||||
//~^ ERROR defining opaque type use does not fully define opaque type: generic parameter `U`
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
error: defining opaque type use does not fully define opaque type: generic parameter `U` is specified as concrete type `()`
|
||||
--> $DIR/issue-68368-non-defining-use.rs:8:1
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-68368-non-defining-use.rs:8:15
|
||||
|
|
||||
LL | fn f<'a>() -> Alias<'a, ()> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/issue-68368-non-defining-use.rs:7:1
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `()` for generic parameter
|
||||
--> $DIR/issue-68368-non-defining-use.rs:7:16
|
||||
|
|
||||
LL | type Alias<'a, U> = impl Trait<U>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -7,7 +7,6 @@ fn main() {}
|
||||
type Two<T, U> = impl Debug;
|
||||
|
||||
fn two<T: Debug>(t: T) -> Two<T, u32> {
|
||||
//~^ ERROR defining opaque type use does not fully define opaque type
|
||||
(t, 4i8)
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,5 @@
|
||||
error: defining opaque type use does not fully define opaque type: generic parameter `U` is specified as concrete type `u32`
|
||||
--> $DIR/not_a_defining_use.rs:9:1
|
||||
|
|
||||
LL | / fn two<T: Debug>(t: T) -> Two<T, u32> {
|
||||
LL | |
|
||||
LL | | (t, 4i8)
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/not_a_defining_use.rs:30:1
|
||||
--> $DIR/not_a_defining_use.rs:29:1
|
||||
|
|
||||
LL | / fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
|
||||
LL | | (t, <U as Bar>::FOO)
|
||||
@ -16,12 +7,12 @@ LL | | }
|
||||
| |_^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/not_a_defining_use.rs:14:1
|
||||
--> $DIR/not_a_defining_use.rs:9:1
|
||||
|
|
||||
LL | / fn three<T: Debug, U>(t: T) -> Two<T, U> {
|
||||
LL | | (t, 5i8)
|
||||
LL | / fn two<T: Debug>(t: T) -> Two<T, u32> {
|
||||
LL | | (t, 4i8)
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user