diff options
author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-03-22 12:30:24 +0200 |
---|---|---|
committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-04-04 08:29:06 +0300 |
commit | 8807b00dd832d199c0e3b83f8311f0842545f528 (patch) | |
tree | c6ca133b41868a1a2561835592f3fc5879aecaaa | |
parent | 8e9a5d928a035a13fea5d134eaa7c1657407692d (diff) | |
download | rust-8807b00dd832d199c0e3b83f8311f0842545f528.tar.gz |
typeck/type_of: let wfcheck handle duplicate generics in opaque types' substs.
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 |