diff options
author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-03-22 12:16:51 +0200 |
---|---|---|
committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-04-04 08:20:58 +0300 |
commit | 8e9a5d928a035a13fea5d134eaa7c1657407692d (patch) | |
tree | 6c235d36eab9d2e682b81ff7a534b34b4aedec37 | |
parent | a98b5340d1768e631e2afbe9d00f2f2813ec1cfb (diff) | |
download | rust-8e9a5d928a035a13fea5d134eaa7c1657407692d.tar.gz |
typeck/type_of: let wfcheck handle concrete types in opaque types' substs.
12 files changed, 71 insertions, 61 deletions
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 30a53cbc397..43bf7660ac2 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -864,13 +864,15 @@ 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() { + 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. @@ -882,9 +884,9 @@ fn check_opaque_types<'fcx, 'tcx>( in defining scope", ) .span_note( - tcx.def_span(param.def_id), + tcx.def_span(generics.param_at(i, tcx).def_id), &format!( - "used non-generic type {} for \ + "used non-generic type `{}` for \ generic parameter", ty, ), @@ -894,7 +896,6 @@ fn check_opaque_types<'fcx, 'tcx>( }, ty::subst::GenericArgKind::Lifetime(region) => { - let param_span = tcx.def_span(param.def_id); if let ty::ReStatic = region { tcx.sess .struct_span_err( @@ -903,14 +904,14 @@ fn check_opaque_types<'fcx, 'tcx>( 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); + seen.entry(region).or_default().push(i); } } @@ -924,20 +925,24 @@ fn check_opaque_types<'fcx, 'tcx>( in defining scope", ) .span_note( - tcx.def_span(param.def_id), + tcx.def_span(generics.param_at(i, tcx).def_id), &format!( - "used non-generic const {} for \ + "used non-generic const `{}` for \ generic parameter", - ty, + ct, ), ) .emit(); } }, - } // match subst - } // for (subst, param) - for (_, spans) in seen { - if spans.len() > 1 { + } // match arg + } // for (arg, param) + for (_, indices) in seen { + if indices.len() > 1 { + 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, diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index 79782c28253..43fd8ae0fff 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -424,7 +424,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } else { let param = opaque_generics.param_at(i, self.tcx); - self.tcx.sess.span_err( + self.tcx.sess.delay_span_bug( span, &format!( "defining opaque type use does not fully define opaque type: \ diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs index 3bc40c43d77..0a4cc9b7fe8 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs @@ -14,6 +14,6 @@ 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> { () } diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr index 316ea97efb5..b871f79aa1d 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -9,14 +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:17:1 - | -LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { -LL | | () -LL | | } - | |_^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs index bb68975cd30..6e922a6911f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -7,6 +7,6 @@ type Cmp<T> = impl 'static; // 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 cmp() -> Cmp<u32> { //~ ERROR non-defining opaque type use in defining scope 5u32 } diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 553b8381b0e..2e3de7d8c6e 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -4,13 +4,17 @@ error: at least one trait must be specified LL | type Cmp<T> = impl 'static; | ^^^^^^^^^^^^ -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:10:1 +error: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:10:13 | -LL | / fn cmp() -> Cmp<u32> { -LL | | 5u32 -LL | | } - | |_^ +LL | fn cmp() -> Cmp<u32> { + | ^^^^^^^^ + | +note: used non-generic type `u32` for generic parameter + --> $DIR/generic_nondefining_use.rs:5:10 + | +LL | type Cmp<T> = impl 'static; + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index 06f1f3430b2..4eb7f7836d8 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -17,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()) diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr index 2ed7e1376c1..55984609437 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,13 +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:19:5 - | -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: 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 `_` 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 previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs index 060336b9661..3b6decbe9c6 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs @@ -6,7 +6,7 @@ trait Trait<T> {} 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() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr index f8ad443f721..c2fa54f50f8 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -1,8 +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, ()> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ + | +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 previous error diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs index ca00e582d34..02485b24e7b 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -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) } diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr index a5deeb3b7a3..cce861b76c9 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -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) @@ -19,10 +10,9 @@ note: previous use here --> $DIR/not_a_defining_use.rs:9:1 | LL | / fn two<T: Debug>(t: T) -> Two<T, u32> { -LL | | LL | | (t, 4i8) LL | | } | |_^ -error: aborting due to 2 previous errors +error: aborting due to previous error |