From 64651138524b45a7e18bec7dcaf143c7fa4f2794 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 22 Mar 2020 11:01:46 +0200 Subject: [PATCH 1/6] typeck/type_of: simplify checking of opaque types with multipler defining uses. --- src/librustc_middle/ty/mod.rs | 48 +++---- src/librustc_typeck/collect/type_of.rs | 121 +++++------------- .../generic_duplicate_param_use3.rs | 2 +- .../generic_duplicate_param_use3.stderr | 4 +- 4 files changed, 53 insertions(+), 122 deletions(-) diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 901365ef69170..9b18233390797 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -1077,48 +1077,42 @@ impl<'tcx> Generics { false } + pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { + if let Some(index) = param_index.checked_sub(self.parent_count) { + &self.params[index] + } else { + tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?")) + .param_at(param_index, tcx) + } + } + pub fn region_param( &'tcx self, param: &EarlyBoundRegion, tcx: TyCtxt<'tcx>, ) -> &'tcx GenericParamDef { - if let Some(index) = param.index.checked_sub(self.parent_count as u32) { - let param = &self.params[index as usize]; - match param.kind { - GenericParamDefKind::Lifetime => param, - _ => bug!("expected lifetime parameter, but found another generic parameter"), - } - } else { - tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?")) - .region_param(param, tcx) + let param = self.param_at(param.index as usize, tcx); + match param.kind { + GenericParamDefKind::Lifetime => param, + _ => bug!("expected lifetime parameter, but found another generic parameter"), } } /// Returns the `GenericParamDef` associated with this `ParamTy`. pub fn type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { - if let Some(index) = param.index.checked_sub(self.parent_count as u32) { - let param = &self.params[index as usize]; - match param.kind { - GenericParamDefKind::Type { .. } => param, - _ => bug!("expected type parameter, but found another generic parameter"), - } - } else { - tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?")) - .type_param(param, tcx) + let param = self.param_at(param.index as usize, tcx); + match param.kind { + GenericParamDefKind::Type { .. } => param, + _ => bug!("expected type parameter, but found another generic parameter"), } } /// Returns the `ConstParameterDef` associated with this `ParamConst`. pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { - if let Some(index) = param.index.checked_sub(self.parent_count as u32) { - let param = &self.params[index as usize]; - match param.kind { - GenericParamDefKind::Const => param, - _ => bug!("expected const parameter, but found another generic parameter"), - } - } else { - tcx.generics_of(self.parent.expect("parent_count>0 but no parent?")) - .const_param(param, tcx) + let param = self.param_at(param.index as usize, tcx); + match param.kind { + GenericParamDefKind::Const => param, + _ => bug!("expected const parameter, but found another generic parameter"), } } } diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index e6099b98dc82b..acf593c291274 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -1,4 +1,4 @@ -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::{struct_span_err, Applicability, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -7,7 +7,7 @@ use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; use rustc_middle::hir::map::Map; -use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; +use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; use rustc_session::parse::feature_err; @@ -369,13 +369,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { struct ConstraintLocator<'tcx> { tcx: TyCtxt<'tcx>, def_id: DefId, - // (first found type span, actual type, mapping from the opaque type's generic - // parameters to the concrete type's generic parameters) - // - // The mapping is an index for each use site of a generic parameter in the concrete type - // - // The indices index into the generic parameters on the opaque type. - found: Option<(Span, Ty<'tcx>, Vec)>, + // (first found type span, actual type) + found: Option<(Span, Ty<'tcx>)>, } impl ConstraintLocator<'_> { @@ -407,14 +402,15 @@ 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); - // used to quickly look up the position of a generic parameter - let mut index_map: FxHashMap = FxHashMap::default(); - // Skipping binder is ok, since we only use this to find generic parameters and - // their positions. - for (idx, subst) in substs.iter().enumerate() { - if let GenericArgKind::Type(ty) = subst.unpack() { + + let opaque_generics = self.tcx.generics_of(self.def_id); + let mut used_params: FxHashSet = FxHashSet::default(); + let mut has_errors = false; + 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 index_map.insert(p, idx).is_some() { + if !used_params.insert(p) { // There was already an entry for `p`, meaning a generic parameter // was used twice. self.tcx.sess.span_err( @@ -428,62 +424,28 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { return; } } else { - self.tcx.sess.delay_span_bug( + let param = opaque_generics.param_at(i, self.tcx); + self.tcx.sess.span_err( span, &format!( - "non-defining opaque ty use in defining scope: {:?}, {:?}", - concrete_type, substs, + "defining opaque type use does not fully define opaque type: \ + generic parameter `{}` is specified as concrete {} `{}`", + param.name, + param.kind.descr(), + arg, ), ); + has_errors = true; } } } - // Compute the index within the opaque type for each generic parameter used in - // the concrete type. - let indices = concrete_type - .subst(self.tcx, substs) - .walk() - .filter_map(|t| match &t.kind { - ty::Param(p) => Some(*index_map.get(p).unwrap()), - _ => None, - }) - .collect(); - let is_param = |ty: Ty<'_>| match ty.kind { - ty::Param(_) => true, - _ => false, - }; - let bad_substs: Vec<_> = substs - .iter() - .enumerate() - .filter_map(|(i, k)| { - if let GenericArgKind::Type(ty) = k.unpack() { Some((i, ty)) } else { None } - }) - .filter(|(_, ty)| !is_param(ty)) - .collect(); - if !bad_substs.is_empty() { - let identity_substs = InternalSubsts::identity_for_item(self.tcx, self.def_id); - for (i, bad_subst) in bad_substs { - self.tcx.sess.span_err( - span, - &format!( - "defining opaque type use does not fully define opaque type: \ - generic parameter `{}` is specified as concrete type `{}`", - identity_substs.type_at(i), - bad_subst - ), - ); - } - } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found { - let mut ty = concrete_type.walk().fuse(); - let mut p_ty = prev_ty.walk().fuse(); - let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) { - // Type parameters are equal to any other type parameter for the purpose of - // concrete type equality, as it is possible to obtain the same type just - // by passing matching parameters to a function. - (ty::Param(_), ty::Param(_)) => true, - _ => t == p, - }); - if !iter_eq || ty.next().is_some() || p_ty.next().is_some() { + + if has_errors { + return; + } + + if let Some((prev_span, prev_ty)) = self.found { + if *concrete_type != prev_ty { debug!("find_opaque_ty_constraints: span={:?}", span); // Found different concrete types for the opaque type. let mut err = self.tcx.sess.struct_span_err( @@ -496,34 +458,9 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ); err.span_note(prev_span, "previous use here"); err.emit(); - } else if indices != *prev_indices { - // Found "same" concrete types, but the generic parameter order differs. - let mut err = self.tcx.sess.struct_span_err( - span, - "concrete type's generic parameters differ from previous defining use", - ); - use std::fmt::Write; - let mut s = String::new(); - write!(s, "expected [").unwrap(); - let list = |s: &mut String, indices: &Vec| { - let mut indices = indices.iter().cloned(); - if let Some(first) = indices.next() { - write!(s, "`{}`", substs[first]).unwrap(); - for i in indices { - write!(s, ", `{}`", substs[i]).unwrap(); - } - } - }; - list(&mut s, prev_indices); - write!(s, "], got [").unwrap(); - list(&mut s, &indices); - write!(s, "]").unwrap(); - err.span_label(span, s); - err.span_note(prev_span, "previous use here"); - err.emit(); } } else { - self.found = Some((span, concrete_type, indices)); + self.found = Some((span, concrete_type)); } } else { debug!( @@ -606,7 +543,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } match locator.found { - Some((_, ty, _)) => ty, + Some((_, ty)) => ty, None => { let span = tcx.def_span(def_id); tcx.sess.span_err(span, "could not find defining uses"); 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 8d3e7f9f42497..ec9f40851c5f5 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 @@ -17,6 +17,6 @@ fn two(t: T, _: U) -> Two { } fn three(_: T, u: U) -> Two { -//~^ concrete type's generic parameters differ from previous defining use +//~^ concrete type differs from previous defining opaque type use u } 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 04dcdc295f9cb..51bee41aba369 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 @@ -7,14 +7,14 @@ LL | | t LL | | } | |_^ -error: concrete type's generic parameters differ from previous defining use +error: concrete type differs from previous defining opaque type use --> $DIR/generic_duplicate_param_use3.rs:19:1 | LL | / fn three(_: T, u: U) -> Two { LL | | LL | | u LL | | } - | |_^ expected [`T`], got [`U`] + | |_^ expected `T`, got `U` | note: previous use here --> $DIR/generic_duplicate_param_use3.rs:15:1 From a98b5340d1768e631e2afbe9d00f2f2813ec1cfb Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 22 Mar 2020 11:15:56 +0200 Subject: [PATCH 2/6] typeck/type_of: don't ignore incorrect defining uses of opaque types. --- src/librustc_typeck/collect/type_of.rs | 10 ++-------- .../type-alias-impl-trait/bound_reduction2.rs | 3 +-- .../bound_reduction2.stderr | 10 ++-------- .../generic_duplicate_param_use.rs | 1 - .../generic_duplicate_param_use.stderr | 10 ++-------- .../generic_duplicate_param_use2.rs | 3 ++- .../generic_duplicate_param_use2.stderr | 20 ++++++++++++++++++- .../generic_duplicate_param_use3.rs | 4 ++-- .../generic_duplicate_param_use3.stderr | 13 ++++++------ .../generic_nondefining_use.rs | 3 +-- .../generic_nondefining_use.stderr | 10 ++-------- .../ui/type-alias-impl-trait/issue-60564.rs | 1 - .../type-alias-impl-trait/issue-60564.stderr | 10 ++-------- .../issue-68368-non-defining-use.rs | 2 +- .../issue-68368-non-defining-use.stderr | 8 +------- .../not_a_defining_use.stderr | 7 ++++--- 16 files changed, 48 insertions(+), 67 deletions(-) diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index acf593c291274..79782c28253a6 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -405,12 +405,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let opaque_generics = self.tcx.generics_of(self.def_id); let mut used_params: FxHashSet = FxHashSet::default(); - let mut has_errors = false; + let mut duplicate_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) { + 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( @@ -421,7 +421,6 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { p, ), ); - return; } } else { let param = opaque_generics.param_at(i, self.tcx); @@ -435,15 +434,10 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { arg, ), ); - has_errors = true; } } } - if has_errors { - return; - } - if let Some((prev_span, prev_ty)) = self.found { if *concrete_type != prev_ty { debug!("find_opaque_ty_constraints: span={:?}", span); 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 1becb1e83a5ac..3bc40c43d777e 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs @@ -8,8 +8,7 @@ trait TraitWithAssoc { } type Foo = impl Trait; -//~^ ERROR could not find defining uses -//~| ERROR the trait bound `T: TraitWithAssoc` is not satisfied +//~^ ERROR the trait bound `T: TraitWithAssoc` is not satisfied trait Trait {} 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 aff558569eaca..316ea97efb5d0 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -10,19 +10,13 @@ LL | fn foo_desugared(_: T) -> Foo | ^^^^^^^^^^^^^^^^ error: defining opaque type use does not fully define opaque type: generic parameter `V` is specified as concrete type `::Assoc` - --> $DIR/bound_reduction2.rs:18:1 + --> $DIR/bound_reduction2.rs:17:1 | LL | / fn foo_desugared(_: T) -> Foo { LL | | () LL | | } | |_^ -error: could not find defining uses - --> $DIR/bound_reduction2.rs:10:1 - | -LL | type Foo = impl Trait; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. 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 165e320be5e9a..3993cebeb447e 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 @@ -6,7 +6,6 @@ fn main() {} // test that unused generic parameters are ok type Two = impl Debug; -//~^ could not find defining uses fn one(t: T) -> Two { //~^ ERROR defining opaque type use restricts opaque type 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 e1794034e20dd..4a02e85faeaa9 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,5 +1,5 @@ error: defining opaque type use restricts opaque type by using the generic parameter `T` twice - --> $DIR/generic_duplicate_param_use.rs:11:1 + --> $DIR/generic_duplicate_param_use.rs:10:1 | LL | / fn one(t: T) -> Two { LL | | @@ -7,11 +7,5 @@ LL | | t LL | | } | |_^ -error: could not find defining uses - --> $DIR/generic_duplicate_param_use.rs:8:1 - | -LL | type Two = impl Debug; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -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_use2.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs index 0adce817c5c37..b1d3260eba345 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,10 +8,11 @@ fn main() {} type Two = impl Debug; fn one(t: T) -> Two { -//~^ defining opaque type use restricts opaque type +//~^ ERROR defining opaque type use restricts opaque type t } fn two(t: T, _: U) -> Two { +//~^ ERROR concrete type differs from previous defining opaque type use 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 a9a51fa0b4bad..f8cc49ba99f8d 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 @@ -7,5 +7,23 @@ LL | | t LL | | } | |_^ -error: aborting due to previous error +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use2.rs:15:1 + | +LL | / fn two(t: T, _: U) -> Two { +LL | | +LL | | t +LL | | } + | |_^ expected `U`, got `T` + | +note: previous use here + --> $DIR/generic_duplicate_param_use2.rs:10:1 + | +LL | / fn one(t: T) -> Two { +LL | | +LL | | t +LL | | } + | |_^ + +error: aborting due to 2 previous errors 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 ec9f40851c5f5..40f20af07b533 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,15 +8,15 @@ fn main() {} type Two = impl Debug; fn one(t: T) -> Two { -//~^ defining opaque type use restricts opaque type +//~^ ERROR defining opaque type use restricts opaque type t } fn two(t: T, _: U) -> Two { +//~^ ERROR concrete type differs from previous defining opaque type use t } fn three(_: T, u: U) -> Two { -//~^ concrete type differs from previous defining opaque type use u } 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 51bee41aba369..1171befd0b17d 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 @@ -8,18 +8,19 @@ LL | | } | |_^ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use3.rs:19:1 + --> $DIR/generic_duplicate_param_use3.rs:15:1 | -LL | / fn three(_: T, u: U) -> Two { +LL | / fn two(t: T, _: U) -> Two { LL | | -LL | | u +LL | | t LL | | } - | |_^ expected `T`, got `U` + | |_^ expected `U`, got `T` | note: previous use here - --> $DIR/generic_duplicate_param_use3.rs:15:1 + --> $DIR/generic_duplicate_param_use3.rs:10:1 | -LL | / fn two(t: T, _: U) -> Two { +LL | / fn one(t: T) -> Two { +LL | | LL | | t LL | | } | |_^ 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 60106eba1756e..bb68975cd3096 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 @@ -3,8 +3,7 @@ fn main() {} type Cmp = impl 'static; -//~^ ERROR could not find defining uses -//~^^ ERROR: at least one trait must be specified +//~^ ERROR: at least one trait must be specified // not a defining use, because it doesn't define *all* possible generics 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 b952aaa79ccee..553b8381b0ebe 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 @@ -5,18 +5,12 @@ LL | type Cmp = 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:11:1 + --> $DIR/generic_nondefining_use.rs:10:1 | LL | / fn cmp() -> Cmp { LL | | 5u32 LL | | } | |_^ -error: could not find defining uses - --> $DIR/generic_nondefining_use.rs:5:1 - | -LL | type Cmp = impl 'static; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +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 73acc92172bad..06f1f3430b2cc 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -6,7 +6,6 @@ trait IterBits { } type IterBitsIter = impl std::iter::Iterator; -//~^ ERROR could not find defining uses impl IterBits for T where 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 9de3e759e1521..2ed7e1376c179 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,5 +1,5 @@ error: defining opaque type use does not fully define opaque type: generic parameter `I` is specified as concrete type `u8` - --> $DIR/issue-60564.rs:20:5 + --> $DIR/issue-60564.rs:19:5 | LL | / fn iter_bits(self, n: u8) -> Self::BitsIter { LL | | @@ -9,11 +9,5 @@ LL | | .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try LL | | } | |_____^ -error: could not find defining uses - --> $DIR/issue-60564.rs:8:1 - | -LL | type IterBitsIter = impl std::iter::Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error 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 d00f8d7a90119..060336b96612a 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 @@ -4,7 +4,7 @@ #![feature(type_alias_impl_trait)] trait Trait {} -type Alias<'a, U> = impl Trait; //~ ERROR could not find defining uses +type Alias<'a, U> = impl Trait; fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR defining opaque type use does not fully define opaque type: generic parameter `U` 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 b585942406fd4..f8ad443f72126 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 @@ -4,11 +4,5 @@ error: defining opaque type use does not fully define opaque type: generic param LL | fn f<'a>() -> Alias<'a, ()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: could not find defining uses - --> $DIR/issue-68368-non-defining-use.rs:7:1 - | -LL | type Alias<'a, U> = impl Trait; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error 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 d68f1bd30a0da..a5deeb3b7a34d 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 @@ -16,10 +16,11 @@ LL | | } | |_^ expected `(T, i8)`, got `(T, ::Blub)` | note: previous use here - --> $DIR/not_a_defining_use.rs:14:1 + --> $DIR/not_a_defining_use.rs:9:1 | -LL | / fn three(t: T) -> Two { -LL | | (t, 5i8) +LL | / fn two(t: T) -> Two { +LL | | +LL | | (t, 4i8) LL | | } | |_^ From 8e9a5d928a035a13fea5d134eaa7c1657407692d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 22 Mar 2020 12:16:51 +0200 Subject: [PATCH 3/6] typeck/type_of: let wfcheck handle concrete types in opaque types' substs. --- src/librustc_typeck/check/wfcheck.rs | 33 +++++++++-------- src/librustc_typeck/collect/type_of.rs | 2 +- .../type-alias-impl-trait/bound_reduction2.rs | 2 +- .../bound_reduction2.stderr | 10 +----- .../generic_nondefining_use.rs | 2 +- .../generic_nondefining_use.stderr | 16 +++++---- .../ui/type-alias-impl-trait/issue-60564.rs | 3 +- .../type-alias-impl-trait/issue-60564.stderr | 35 +++++++++++++------ .../issue-68368-non-defining-use.rs | 2 +- .../issue-68368-non-defining-use.stderr | 12 +++++-- .../not_a_defining_use.rs | 1 - .../not_a_defining_use.stderr | 14 ++------ 12 files changed, 71 insertions(+), 61 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 30a53cbc397e8..43bf7660ac29c 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` 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 79782c28253a6..43fd8ae0fff57 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 3bc40c43d777e..0a4cc9b7fe8be 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 {} impl Trait for () {} -fn foo_desugared(_: T) -> Foo { //~ ERROR does not fully define +fn foo_desugared(_: T) -> Foo { () } 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 316ea97efb5d0..b871f79aa1dc5 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) -> Foo { | ^^^^^^^^^^^^^^^^ -error: defining opaque type use does not fully define opaque type: generic parameter `V` is specified as concrete type `::Assoc` - --> $DIR/bound_reduction2.rs:17:1 - | -LL | / fn foo_desugared(_: T) -> Foo { -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 bb68975cd3096..6e922a6911f53 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 = impl 'static; // not a defining use, because it doesn't define *all* possible generics -fn cmp() -> Cmp { //~ ERROR defining opaque type use does not fully define +fn cmp() -> Cmp { //~ 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 553b8381b0ebe..2e3de7d8c6e2a 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 = 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 { -LL | | 5u32 -LL | | } - | |_^ +LL | fn cmp() -> Cmp { + | ^^^^^^^^ + | +note: used non-generic type `u32` for generic parameter + --> $DIR/generic_nondefining_use.rs:5:10 + | +LL | type Cmp = 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 06f1f3430b2cc..4eb7f7836d869 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; 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 2ed7e1376c179..55984609437b0 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 = impl std::iter::Iterator; + | ^ + +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 = impl std::iter::Iterator; + | ^ -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 060336b96612a..3b6decbe9c65e 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 {} type Alias<'a, U> = impl Trait; 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 f8ad443f72126..c2fa54f50f881 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; + | ^ 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 ca00e582d3442..02485b24e7b8a 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 = impl Debug; fn two(t: T) -> Two { - //~^ 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 a5deeb3b7a34d..cce861b76c95e 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: T) -> Two { -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: T) -> Two { LL | | (t, ::FOO) @@ -19,10 +10,9 @@ note: previous use here --> $DIR/not_a_defining_use.rs:9:1 | LL | / fn two(t: T) -> Two { -LL | | LL | | (t, 4i8) LL | | } | |_^ -error: aborting due to 2 previous errors +error: aborting due to previous error From 8807b00dd832d199c0e3b83f8311f0842545f528 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 22 Mar 2020 12:30:24 +0200 Subject: [PATCH 4/6] typeck/type_of: let wfcheck handle duplicate generics in opaque types' substs. --- src/librustc_typeck/check/wfcheck.rs | 93 ++++++++----------- src/librustc_typeck/collect/type_of.rs | 51 +++++----- .../generic_duplicate_param_use.rs | 2 +- .../generic_duplicate_param_use.stderr | 17 ++-- .../generic_duplicate_param_use2.rs | 1 - .../generic_duplicate_param_use2.stderr | 14 +-- .../generic_duplicate_param_use3.rs | 1 - .../generic_duplicate_param_use3.stderr | 14 +-- .../generic_duplicate_param_use4.rs | 2 +- .../generic_duplicate_param_use4.stderr | 17 ++-- 10 files changed, 93 insertions(+), 119 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 43bf7660ac29c..b0ff17ad56d7c 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` 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` 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 43fd8ae0fff57..c2a32ffe4828f 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 = FxHashSet::default(); - let mut duplicate_params: FxHashSet = 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 3993cebeb447e..26bb644f990f6 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 = impl Debug; fn one(t: T) -> Two { -//~^ 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 4a02e85faeaa9..6275549eef7b9 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: T) -> Two { -LL | | -LL | | t -LL | | } - | |_^ +LL | fn one(t: T) -> Two { + | ^^^^^^^^^ + | +note: type used multiple times + --> $DIR/generic_duplicate_param_use.rs:8:10 + | +LL | type Two = 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 b1d3260eba345..2b98d8fc63a11 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 = impl Debug; fn one(t: T) -> Two { -//~^ 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 f8cc49ba99f8d..8170c671f68cd 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: T) -> Two { -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: T, _: U) -> Two { LL | | @@ -20,10 +11,9 @@ note: previous use here --> $DIR/generic_duplicate_param_use2.rs:10:1 | LL | / fn one(t: T) -> Two { -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 40f20af07b533..d9133fd11f7cd 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 = impl Debug; fn one(t: T) -> Two { -//~^ 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 1171befd0b17d..86dd33684005b 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: T) -> Two { -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: T, _: U) -> Two { LL | | @@ -20,10 +11,9 @@ note: previous use here --> $DIR/generic_duplicate_param_use3.rs:10:1 | LL | / fn one(t: T) -> Two { -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 65f7d7f485d49..40388c3b6c88a 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 = impl Debug; fn one(t: T) -> Two { -//~^ 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 082177b82128d..fcf01f5164ae4 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: T) -> Two { -LL | | -LL | | t -LL | | } - | |_^ +LL | fn one(t: T) -> Two { + | ^^^^^^^^^ + | +note: type used multiple times + --> $DIR/generic_duplicate_param_use4.rs:8:10 + | +LL | type Two = impl Debug; + | ^ ^ error: aborting due to previous error From ea7999b4f3511c2fda3c7c8955b6d03573868139 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 22 Mar 2020 14:15:02 +0200 Subject: [PATCH 5/6] tests: add tests for lifetime and const params of opaque types. --- .../generic_duplicate_param_use.rs | 19 +++++++-- .../generic_duplicate_param_use.stderr | 38 ++++++++++++++---- .../generic_nondefining_use.rs | 25 +++++++++--- .../generic_nondefining_use.stderr | 39 +++++++++++++------ 4 files changed, 94 insertions(+), 27 deletions(-) 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 26bb644f990f6..4503607a83638 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 @@ -1,13 +1,26 @@ -#![feature(type_alias_impl_trait)] +#![feature(type_alias_impl_trait, const_generics)] +#![allow(incomplete_features)] use std::fmt::Debug; fn main() {} // test that unused generic parameters are ok -type Two = impl Debug; +type TwoTys = impl Debug; +type TwoLifetimes<'a, 'b> = impl Debug; +type TwoConsts = impl Debug; -fn one(t: T) -> Two { +fn one_ty(t: T) -> TwoTys { +//~^ ERROR non-defining opaque type use in defining scope + t +} + +fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { +//~^ ERROR non-defining opaque type use in defining scope + t +} + +fn one_const(t: *mut [u8; N]) -> TwoConsts { //~^ 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 6275549eef7b9..b4757e2763d06 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,14 +1,38 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:10:27 + --> $DIR/generic_duplicate_param_use.rs:13:30 | -LL | fn one(t: T) -> Two { - | ^^^^^^^^^ +LL | fn one_ty(t: T) -> TwoTys { + | ^^^^^^^^^^^^ | note: type used multiple times - --> $DIR/generic_duplicate_param_use.rs:8:10 + --> $DIR/generic_duplicate_param_use.rs:9:13 | -LL | type Two = impl Debug; - | ^ ^ +LL | type TwoTys = impl Debug; + | ^ ^ -error: aborting due to previous error +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:18:36 + | +LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime used multiple times + --> $DIR/generic_duplicate_param_use.rs:10:19 + | +LL | type TwoLifetimes<'a, 'b> = impl Debug; + | ^^ ^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:23:50 + | +LL | fn one_const(t: *mut [u8; N]) -> TwoConsts { + | ^^^^^^^^^^^^^^^ + | +note: constant used multiple times + --> $DIR/generic_duplicate_param_use.rs:11:22 + | +LL | type TwoConsts = impl Debug; + | ^ ^ + +error: aborting due to 3 previous errors 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 6e922a6911f53..b1782120f84cc 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 @@ -1,12 +1,27 @@ -#![feature(type_alias_impl_trait)] +#![feature(type_alias_impl_trait, const_generics)] +#![allow(incomplete_features)] + +use std::fmt::Debug; fn main() {} -type Cmp = impl 'static; -//~^ ERROR: at least one trait must be specified +type OneTy = impl Debug; +type OneLifetime<'a> = impl Debug; +type OneConst = impl Debug; +// Not defining uses, because they doesn't define *all* possible generics. -// not a defining use, because it doesn't define *all* possible generics -fn cmp() -> Cmp { //~ ERROR non-defining opaque type use in defining scope +fn concrete_ty() -> OneTy { +//~^ ERROR non-defining opaque type use in defining scope 5u32 } + +fn concrete_lifetime() -> OneLifetime<'static> { +//~^ ERROR non-defining opaque type use in defining scope + 6u32 +} + +fn concrete_const() -> OneConst<{123}> { +//~^ ERROR non-defining opaque type use in defining scope + 7u32 +} 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 2e3de7d8c6e2a..b0ffc4a5ef61d 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 @@ -1,20 +1,35 @@ -error: at least one trait must be specified - --> $DIR/generic_nondefining_use.rs:5:15 +error: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:14:21 + | +LL | fn concrete_ty() -> OneTy { + | ^^^^^^^^^^ + | +note: used non-generic type `u32` for generic parameter + --> $DIR/generic_nondefining_use.rs:8:12 | -LL | type Cmp = impl 'static; - | ^^^^^^^^^^^^ +LL | type OneTy = impl Debug; + | ^ error: non-defining opaque type use in defining scope - --> $DIR/generic_nondefining_use.rs:10:13 + --> $DIR/generic_nondefining_use.rs:19:27 | -LL | fn cmp() -> Cmp { - | ^^^^^^^^ +LL | type OneLifetime<'a> = impl Debug; + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +... +LL | fn concrete_lifetime() -> OneLifetime<'static> { + | ^^^^^^^^^^^^^^^^^^^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:24:24 | -note: used non-generic type `u32` for generic parameter - --> $DIR/generic_nondefining_use.rs:5:10 +LL | fn concrete_const() -> OneConst<{123}> { + | ^^^^^^^^^^^^^^^ + | +note: used non-generic constant `123usize` for generic parameter + --> $DIR/generic_nondefining_use.rs:10:21 | -LL | type Cmp = impl 'static; - | ^ +LL | type OneConst = impl Debug; + | ^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors From 8ad149a0e0810cb2ef17b2b0aef18c9a2a9062b0 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 22 Mar 2020 14:45:32 +0200 Subject: [PATCH 6/6] typeck/type_of: only early-bound and (free) late-bound lifetimes are parameters. --- src/librustc_typeck/collect/type_of.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index c2a32ffe4828f..d45c82700689a 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -411,7 +411,9 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { for (i, arg) in substs.iter().enumerate() { let arg_is_param = match arg.unpack() { GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)), - GenericArgKind::Lifetime(lt) => !matches!(lt, ty::ReStatic), + GenericArgKind::Lifetime(lt) => { + matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_)) + } GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)), };