Skip to content

Commit 8807b00

Browse files
committed
typeck/type_of: let wfcheck handle duplicate generics in opaque types' substs.
1 parent 8e9a5d9 commit 8807b00

10 files changed

+93
-119
lines changed

src/librustc_typeck/check/wfcheck.rs

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_hir::def_id::DefId;
99
use rustc_hir::itemlikevisit::ParItemLikeVisitor;
1010
use rustc_hir::lang_items;
1111
use rustc_hir::ItemKind;
12-
use rustc_middle::ty::subst::{InternalSubsts, Subst};
12+
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
1313
use rustc_middle::ty::trait_def::TraitSpecializationKind;
1414
use rustc_middle::ty::{
1515
self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
@@ -870,38 +870,17 @@ fn check_opaque_types<'fcx, 'tcx>(
870870
let opaque_hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
871871
if may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
872872
trace!("check_opaque_types: may define, generics={:#?}", generics);
873-
let mut seen: FxHashMap<_, Vec<_>> = FxHashMap::default();
873+
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
874874
for (i, &arg) in substs.iter().enumerate() {
875-
match arg.unpack() {
876-
ty::subst::GenericArgKind::Type(ty) => match ty.kind {
877-
ty::Param(..) => {}
878-
// Prevent `fn foo() -> Foo<u32>` from being defining.
879-
_ => {
880-
tcx.sess
881-
.struct_span_err(
882-
span,
883-
"non-defining opaque type use \
884-
in defining scope",
885-
)
886-
.span_note(
887-
tcx.def_span(generics.param_at(i, tcx).def_id),
888-
&format!(
889-
"used non-generic type `{}` for \
890-
generic parameter",
891-
ty,
892-
),
893-
)
894-
.emit();
895-
}
896-
},
875+
let arg_is_param = match arg.unpack() {
876+
GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
897877

898-
ty::subst::GenericArgKind::Lifetime(region) => {
878+
GenericArgKind::Lifetime(region) => {
899879
if let ty::ReStatic = region {
900880
tcx.sess
901881
.struct_span_err(
902882
span,
903-
"non-defining opaque type use \
904-
in defining scope",
883+
"non-defining opaque type use in defining scope",
905884
)
906885
.span_label(
907886
tcx.def_span(generics.param_at(i, tcx).def_id),
@@ -910,46 +889,52 @@ fn check_opaque_types<'fcx, 'tcx>(
910889
opaque type",
911890
)
912891
.emit();
913-
} else {
914-
seen.entry(region).or_default().push(i);
892+
continue;
915893
}
894+
895+
true
916896
}
917897

918-
ty::subst::GenericArgKind::Const(ct) => match ct.val {
919-
ty::ConstKind::Param(_) => {}
920-
_ => {
921-
tcx.sess
922-
.struct_span_err(
923-
span,
924-
"non-defining opaque type use \
925-
in defining scope",
926-
)
927-
.span_note(
928-
tcx.def_span(generics.param_at(i, tcx).def_id),
929-
&format!(
930-
"used non-generic const `{}` for \
931-
generic parameter",
932-
ct,
933-
),
934-
)
935-
.emit();
936-
}
937-
},
938-
} // match arg
898+
GenericArgKind::Const(ct) => {
899+
matches!(ct.val, ty::ConstKind::Param(_))
900+
}
901+
};
902+
903+
if arg_is_param {
904+
seen_params.entry(arg).or_default().push(i);
905+
} else {
906+
// Prevent `fn foo() -> Foo<u32>` from being defining.
907+
let opaque_param = generics.param_at(i, tcx);
908+
tcx.sess
909+
.struct_span_err(
910+
span,
911+
"non-defining opaque type use in defining scope",
912+
)
913+
.span_note(
914+
tcx.def_span(opaque_param.def_id),
915+
&format!(
916+
"used non-generic {} `{}` for generic parameter",
917+
opaque_param.kind.descr(),
918+
arg,
919+
),
920+
)
921+
.emit();
922+
}
939923
} // for (arg, param)
940-
for (_, indices) in seen {
924+
925+
for (_, indices) in seen_params {
941926
if indices.len() > 1 {
927+
let descr = generics.param_at(indices[0], tcx).kind.descr();
942928
let spans: Vec<_> = indices
943929
.into_iter()
944930
.map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
945931
.collect();
946932
tcx.sess
947933
.struct_span_err(
948934
span,
949-
"non-defining opaque type use \
950-
in defining scope",
935+
"non-defining opaque type use in defining scope",
951936
)
952-
.span_note(spans, "lifetime used multiple times")
937+
.span_note(spans, &format!("{} used multiple times", descr))
953938
.emit();
954939
}
955940
}

src/librustc_typeck/collect/type_of.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -403,38 +403,43 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
403403
// FIXME(oli-obk): trace the actual span from inference to improve errors.
404404
let span = self.tcx.def_span(def_id);
405405

406+
// HACK(eddyb) this check shouldn't be needed, as `wfcheck`
407+
// performs the same checks, in theory, but I've kept it here
408+
// using `delay_span_bug`, just in case `wfcheck` slips up.
406409
let opaque_generics = self.tcx.generics_of(self.def_id);
407-
let mut used_params: FxHashSet<ty::ParamTy> = FxHashSet::default();
408-
let mut duplicate_params: FxHashSet<ty::ParamTy> = FxHashSet::default();
410+
let mut used_params: FxHashSet<_> = FxHashSet::default();
409411
for (i, arg) in substs.iter().enumerate() {
410-
// FIXME(eddyb) enforce lifetime and const param 1:1 mapping.
411-
if let GenericArgKind::Type(ty) = arg.unpack() {
412-
if let ty::Param(p) = ty.kind {
413-
if !used_params.insert(p) && duplicate_params.insert(p) {
414-
// There was already an entry for `p`, meaning a generic parameter
415-
// was used twice.
416-
self.tcx.sess.span_err(
417-
span,
418-
&format!(
419-
"defining opaque type use restricts opaque \
420-
type by using the generic parameter `{}` twice",
421-
p,
422-
),
423-
);
424-
}
425-
} else {
426-
let param = opaque_generics.param_at(i, self.tcx);
412+
let arg_is_param = match arg.unpack() {
413+
GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
414+
GenericArgKind::Lifetime(lt) => !matches!(lt, ty::ReStatic),
415+
GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
416+
};
417+
418+
if arg_is_param {
419+
if !used_params.insert(arg) {
420+
// There was already an entry for `arg`, meaning a generic parameter
421+
// was used twice.
427422
self.tcx.sess.delay_span_bug(
428423
span,
429424
&format!(
430-
"defining opaque type use does not fully define opaque type: \
431-
generic parameter `{}` is specified as concrete {} `{}`",
432-
param.name,
433-
param.kind.descr(),
425+
"defining opaque type use restricts opaque \
426+
type by using the generic parameter `{}` twice",
434427
arg,
435428
),
436429
);
437430
}
431+
} else {
432+
let param = opaque_generics.param_at(i, self.tcx);
433+
self.tcx.sess.delay_span_bug(
434+
span,
435+
&format!(
436+
"defining opaque type use does not fully define opaque type: \
437+
generic parameter `{}` is specified as concrete {} `{}`",
438+
param.name,
439+
param.kind.descr(),
440+
arg,
441+
),
442+
);
438443
}
439444
}
440445

src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ fn main() {}
88
type Two<T, U> = impl Debug;
99

1010
fn one<T: Debug>(t: T) -> Two<T, T> {
11-
//~^ ERROR defining opaque type use restricts opaque type
11+
//~^ ERROR non-defining opaque type use in defining scope
1212
t
1313
}
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
2-
--> $DIR/generic_duplicate_param_use.rs:10:1
1+
error: non-defining opaque type use in defining scope
2+
--> $DIR/generic_duplicate_param_use.rs:10:27
33
|
4-
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
5-
LL | |
6-
LL | | t
7-
LL | | }
8-
| |_^
4+
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
5+
| ^^^^^^^^^
6+
|
7+
note: type used multiple times
8+
--> $DIR/generic_duplicate_param_use.rs:8:10
9+
|
10+
LL | type Two<T, U> = impl Debug;
11+
| ^ ^
912

1013
error: aborting due to previous error
1114

src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ fn main() {}
88
type Two<T, U> = impl Debug;
99

1010
fn one<T: Debug>(t: T) -> Two<T, T> {
11-
//~^ ERROR defining opaque type use restricts opaque type
1211
t
1312
}
1413

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
1-
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
2-
--> $DIR/generic_duplicate_param_use2.rs:10:1
3-
|
4-
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
5-
LL | |
6-
LL | | t
7-
LL | | }
8-
| |_^
9-
101
error: concrete type differs from previous defining opaque type use
11-
--> $DIR/generic_duplicate_param_use2.rs:15:1
2+
--> $DIR/generic_duplicate_param_use2.rs:14:1
123
|
134
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
145
LL | |
@@ -20,10 +11,9 @@ note: previous use here
2011
--> $DIR/generic_duplicate_param_use2.rs:10:1
2112
|
2213
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
23-
LL | |
2414
LL | | t
2515
LL | | }
2616
| |_^
2717

28-
error: aborting due to 2 previous errors
18+
error: aborting due to previous error
2919

src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ fn main() {}
88
type Two<T, U> = impl Debug;
99

1010
fn one<T: Debug>(t: T) -> Two<T, T> {
11-
//~^ ERROR defining opaque type use restricts opaque type
1211
t
1312
}
1413

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
1-
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
2-
--> $DIR/generic_duplicate_param_use3.rs:10:1
3-
|
4-
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
5-
LL | |
6-
LL | | t
7-
LL | | }
8-
| |_^
9-
101
error: concrete type differs from previous defining opaque type use
11-
--> $DIR/generic_duplicate_param_use3.rs:15:1
2+
--> $DIR/generic_duplicate_param_use3.rs:14:1
123
|
134
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
145
LL | |
@@ -20,10 +11,9 @@ note: previous use here
2011
--> $DIR/generic_duplicate_param_use3.rs:10:1
2112
|
2213
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
23-
LL | |
2414
LL | | t
2515
LL | | }
2616
| |_^
2717

28-
error: aborting due to 2 previous errors
18+
error: aborting due to previous error
2919

src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn main() {}
88
type Two<T, U> = impl Debug;
99

1010
fn one<T: Debug>(t: T) -> Two<T, T> {
11-
//~^ ERROR defining opaque type use restricts opaque type
11+
//~^ ERROR non-defining opaque type use in defining scope
1212
t
1313
}
1414

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
2-
--> $DIR/generic_duplicate_param_use4.rs:10:1
1+
error: non-defining opaque type use in defining scope
2+
--> $DIR/generic_duplicate_param_use4.rs:10:27
33
|
4-
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
5-
LL | |
6-
LL | | t
7-
LL | | }
8-
| |_^
4+
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
5+
| ^^^^^^^^^
6+
|
7+
note: type used multiple times
8+
--> $DIR/generic_duplicate_param_use4.rs:8:10
9+
|
10+
LL | type Two<T, U> = impl Debug;
11+
| ^ ^
912

1013
error: aborting due to previous error
1114

0 commit comments

Comments
 (0)