mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
typeck/type_of: let wfcheck handle duplicate generics in opaque types' substs.
This commit is contained in:
parent
8e9a5d928a
commit
8807b00dd8
@ -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,
|
||||
@ -870,38 +870,17 @@ fn check_opaque_types<'fcx, 'tcx>(
|
||||
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();
|
||||
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
|
||||
for (i, &arg) in substs.iter().enumerate() {
|
||||
match arg.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(generics.param_at(i, tcx).def_id),
|
||||
&format!(
|
||||
"used non-generic type `{}` for \
|
||||
generic parameter",
|
||||
ty,
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
},
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
|
||||
|
||||
ty::subst::GenericArgKind::Lifetime(region) => {
|
||||
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(
|
||||
tcx.def_span(generics.param_at(i, tcx).def_id),
|
||||
@ -910,35 +889,42 @@ fn check_opaque_types<'fcx, 'tcx>(
|
||||
opaque type",
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
seen.entry(region).or_default().push(i);
|
||||
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(generics.param_at(i, tcx).def_id),
|
||||
&format!(
|
||||
"used non-generic const `{}` for \
|
||||
generic parameter",
|
||||
ct,
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
},
|
||||
} // match arg
|
||||
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",
|
||||
)
|
||||
.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 {
|
||||
|
||||
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))
|
||||
@ -946,10 +932,9 @@ fn check_opaque_types<'fcx, '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(spans, &format!("{} used multiple times", descr))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
@ -403,38 +403,43 @@ 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);
|
||||
|
||||
// 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<ty::ParamTy> = FxHashSet::default();
|
||||
let mut duplicate_params: FxHashSet<ty::ParamTy> = FxHashSet::default();
|
||||
let mut used_params: FxHashSet<_> = FxHashSet::default();
|
||||
for (i, arg) in substs.iter().enumerate() {
|
||||
// FIXME(eddyb) enforce lifetime and const param 1:1 mapping.
|
||||
if let GenericArgKind::Type(ty) = arg.unpack() {
|
||||
if let ty::Param(p) = ty.kind {
|
||||
if !used_params.insert(p) && duplicate_params.insert(p) {
|
||||
// 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,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let param = opaque_generics.param_at(i, self.tcx);
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
|
||||
GenericArgKind::Lifetime(lt) => !matches!(lt, ty::ReStatic),
|
||||
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!(
|
||||
"defining opaque type use does not fully define opaque type: \
|
||||
generic parameter `{}` is specified as concrete {} `{}`",
|
||||
param.name,
|
||||
param.kind.descr(),
|
||||
"defining opaque type use restricts opaque \
|
||||
type by using the generic parameter `{}` twice",
|
||||
arg,
|
||||
),
|
||||
);
|
||||
}
|
||||
} 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 {} `{}`",
|
||||
param.name,
|
||||
param.kind.descr(),
|
||||
arg,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,6 @@ 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_use.rs:10:1
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.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_use.rs:8:10
|
||||
|
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,7 +8,6 @@ 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
|
||||
t
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,5 @@
|
||||
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
|
||||
--> $DIR/generic_duplicate_param_use2.rs:10:1
|
||||
|
|
||||
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
LL | |
|
||||
LL | | t
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/generic_duplicate_param_use2.rs:15:1
|
||||
--> $DIR/generic_duplicate_param_use2.rs:14:1
|
||||
|
|
||||
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||
LL | |
|
||||
@ -20,10 +11,9 @@ 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 | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,7 +8,6 @@ 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
|
||||
t
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,5 @@
|
||||
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
|
||||
--> $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 differs from previous defining opaque type use
|
||||
--> $DIR/generic_duplicate_param_use3.rs:15:1
|
||||
--> $DIR/generic_duplicate_param_use3.rs:14:1
|
||||
|
|
||||
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||
LL | |
|
||||
@ -20,10 +11,9 @@ 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: 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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user