summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2020-03-22 12:30:24 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2020-04-04 08:29:06 +0300
commit8807b00dd832d199c0e3b83f8311f0842545f528 (patch)
treec6ca133b41868a1a2561835592f3fc5879aecaaa
parent8e9a5d928a035a13fea5d134eaa7c1657407692d (diff)
downloadrust-8807b00dd832d199c0e3b83f8311f0842545f528.tar.gz
typeck/type_of: let wfcheck handle duplicate generics in opaque types' substs.
-rw-r--r--src/librustc_typeck/check/wfcheck.rs93
-rw-r--r--src/librustc_typeck/collect/type_of.rs51
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr17
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr17
10 files changed, 93 insertions, 119 deletions
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 43bf7660ac2..b0ff17ad56d 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -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();
}
}
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index 43fd8ae0fff..c2a32ffe482 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -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,
+ ),
+ );
}
}
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
index 3993cebeb44..26bb644f990 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
@@ -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
}
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
index 4a02e85faea..6275549eef7 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
@@ -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
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
index b1d3260eba3..2b98d8fc63a 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
@@ -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
}
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
index f8cc49ba99f..8170c671f68 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
@@ -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
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
index 40f20af07b5..d9133fd11f7 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
@@ -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
}
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
index 1171befd0b1..86dd3368400 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
@@ -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
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
index 65f7d7f485d..40388c3b6c8 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
@@ -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
}
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
index 082177b8212..fcf01f5164a 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
@@ -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