From 600607f45a400e5930126b5ef1dc05f5644e95c3 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 20 Oct 2019 17:16:58 +0100 Subject: [PATCH 01/16] Move `search_for_adt_without_structural_match` to `ty/mod` --- src/librustc/ty/mod.rs | 117 ++++++++++++++++++++++++- src/librustc_mir/hair/pattern/mod.rs | 122 +-------------------------- 2 files changed, 116 insertions(+), 123 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d377b7328e80b..77d8141c9688c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -4,7 +4,7 @@ pub use self::Variance::*; pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; -pub use self::fold::TypeFoldable; +pub use self::fold::{TypeFoldable, TypeVisitor}; use crate::hir::{map as hir_map, GlobMap, TraitMap}; use crate::hir::Node; @@ -50,7 +50,7 @@ use syntax::symbol::{kw, sym, Symbol, InternedString}; use syntax_pos::Span; use smallvec; -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use rustc_index::vec::{Idx, IndexVec}; @@ -3393,6 +3393,119 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn_like.asyncness() } +/// This method traverses the structure of `ty`, trying to find an +/// instance of an ADT (i.e. struct or enum) that was declared without +/// the `#[structural_match]` attribute. +/// +/// The "structure of a type" includes all components that would be +/// considered when doing a pattern match on a constant of that +/// type. +/// +/// * This means this method descends into fields of structs/enums, +/// and also descends into the inner type `T` of `&T` and `&mut T` +/// +/// * The traversal doesn't dereference unsafe pointers (`*const T`, +/// `*mut T`), and it does not visit the type arguments of an +/// instantiated generic like `PhantomData`. +/// +/// The reason we do this search is Rust currently require all ADTs +/// reachable from a constant's type to be annotated with +/// `#[structural_match]`, an attribute which essentially says that +/// the implementation of `PartialEq::eq` behaves *equivalently* to a +/// comparison against the unfolded structure. +/// +/// For more background on why Rust has this requirement, and issues +/// that arose when the requirement was not enforced completely, see +/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. +pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>) + -> Option<&'tcx AdtDef> +{ + let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; + ty.visit_with(&mut search); + return search.found; + + struct Search<'tcx> { + tcx: TyCtxt<'tcx>, + + // records the first ADT we find without `#[structural_match` + found: Option<&'tcx AdtDef>, + + // tracks ADT's previously encountered during search, so that + // we will not recur on them again. + seen: FxHashSet, + } + + impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + debug!("Search visiting ty: {:?}", ty); + + let (adt_def, substs) = match ty.kind { + ty::Adt(adt_def, substs) => (adt_def, substs), + ty::RawPtr(..) => { + // `#[structural_match]` ignores substructure of + // `*const _`/`*mut _`, so skip super_visit_with + // + // (But still tell caller to continue search.) + return false; + } + ty::FnDef(..) | ty::FnPtr(..) => { + // types of formals and return in `fn(_) -> _` are also irrelevant + // + // (But still tell caller to continue search.) + return false; + } + ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) + => { + // rust-lang/rust#62336: ignore type of contents + // for empty array. + return false; + } + _ => { + ty.super_visit_with(self); + return false; + } + }; + + if !self.tcx.has_attr(adt_def.did, sym::structural_match) { + self.found = Some(&adt_def); + debug!("Search found adt_def: {:?}", adt_def); + return true // Halt visiting! + } + + if !self.seen.insert(adt_def.did) { + debug!("Search already seen adt_def: {:?}", adt_def); + // let caller continue its search + return false; + } + + // `#[structural_match]` does not care about the + // instantiation of the generics in an ADT (it + // instead looks directly at its fields outside + // this match), so we skip super_visit_with. + // + // (Must not recur on substs for `PhantomData` cf + // rust-lang/rust#55028 and rust-lang/rust#55837; but also + // want to skip substs when only uses of generic are + // behind unsafe pointers `*const T`/`*mut T`.) + + // even though we skip super_visit_with, we must recur on + // fields of ADT. + let tcx = self.tcx; + for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) { + if field_ty.visit_with(self) { + // found an ADT without `#[structural_match]`; halt visiting! + assert!(self.found.is_some()); + return true; + } + } + + // Even though we do not want to recur on substs, we do + // want our caller to continue its own search. + false + } + } +} pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 58480912929b3..d996881221857 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -25,7 +25,6 @@ use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc::hir::ptr::P; use rustc_index::vec::Idx; -use rustc_data_structures::fx::FxHashSet; use std::cmp::Ordering; use std::fmt; @@ -1000,7 +999,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if self.include_lint_checks && !saw_error { // If we were able to successfully convert the const to some pat, double-check // that the type of the const obeys `#[structural_match]` constraint. - if let Some(adt_def) = search_for_adt_without_structural_match(self.tcx, cv.ty) { + if let Some(adt_def) = ty::search_for_adt_without_structural_match(self.tcx, cv.ty) { let path = self.tcx.def_path_str(adt_def.did); let msg = format!( @@ -1169,125 +1168,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } } -/// This method traverses the structure of `ty`, trying to find an -/// instance of an ADT (i.e. struct or enum) that was declared without -/// the `#[structural_match]` attribute. -/// -/// The "structure of a type" includes all components that would be -/// considered when doing a pattern match on a constant of that -/// type. -/// -/// * This means this method descends into fields of structs/enums, -/// and also descends into the inner type `T` of `&T` and `&mut T` -/// -/// * The traversal doesn't dereference unsafe pointers (`*const T`, -/// `*mut T`), and it does not visit the type arguments of an -/// instantiated generic like `PhantomData`. -/// -/// The reason we do this search is Rust currently require all ADT's -/// reachable from a constant's type to be annotated with -/// `#[structural_match]`, an attribute which essentially says that -/// the implementation of `PartialEq::eq` behaves *equivalently* to a -/// comparison against the unfolded structure. -/// -/// For more background on why Rust has this requirement, and issues -/// that arose when the requirement was not enforced completely, see -/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. -fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>) - -> Option<&'tcx AdtDef> -{ - // Import here (not mod level), because `TypeFoldable::fold_with` - // conflicts with `PatternFoldable::fold_with` - use crate::rustc::ty::fold::TypeVisitor; - use crate::rustc::ty::TypeFoldable; - - let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; - ty.visit_with(&mut search); - return search.found; - - struct Search<'tcx> { - tcx: TyCtxt<'tcx>, - - // records the first ADT we find without `#[structural_match` - found: Option<&'tcx AdtDef>, - - // tracks ADT's previously encountered during search, so that - // we will not recur on them again. - seen: FxHashSet, - } - - impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - debug!("Search visiting ty: {:?}", ty); - - let (adt_def, substs) = match ty.kind { - ty::Adt(adt_def, substs) => (adt_def, substs), - ty::RawPtr(..) => { - // `#[structural_match]` ignores substructure of - // `*const _`/`*mut _`, so skip super_visit_with - // - // (But still tell caller to continue search.) - return false; - } - ty::FnDef(..) | ty::FnPtr(..) => { - // types of formals and return in `fn(_) -> _` are also irrelevant - // - // (But still tell caller to continue search.) - return false; - } - ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) - => { - // rust-lang/rust#62336: ignore type of contents - // for empty array. - return false; - } - _ => { - ty.super_visit_with(self); - return false; - } - }; - - if !self.tcx.has_attr(adt_def.did, sym::structural_match) { - self.found = Some(&adt_def); - debug!("Search found adt_def: {:?}", adt_def); - return true // Halt visiting! - } - - if !self.seen.insert(adt_def.did) { - debug!("Search already seen adt_def: {:?}", adt_def); - // let caller continue its search - return false; - } - - // `#[structural_match]` does not care about the - // instantiation of the generics in an ADT (it - // instead looks directly at its fields outside - // this match), so we skip super_visit_with. - // - // (Must not recur on substs for `PhantomData` cf - // rust-lang/rust#55028 and rust-lang/rust#55837; but also - // want to skip substs when only uses of generic are - // behind unsafe pointers `*const T`/`*mut T`.) - - // even though we skip super_visit_with, we must recur on - // fields of ADT. - let tcx = self.tcx; - for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) { - if field_ty.visit_with(self) { - // found an ADT without `#[structural_match]`; halt visiting! - assert!(self.found.is_some()); - return true; - } - } - - // Even though we do not want to recur on substs, we do - // want our caller to continue its own search. - false - } - } -} - impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx From bbd53deaeb79e78162524e18ca29211745e2d18e Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 20 Oct 2019 17:17:12 +0100 Subject: [PATCH 02/16] Forbid non-`structural_match` types in const generics --- src/librustc_typeck/collect.rs | 11 +++++++++ src/librustc_typeck/error_codes.rs | 24 +++++++++++++++++++ .../forbid-non-structural_match-types.rs | 13 ++++++++++ .../forbid-non-structural_match-types.stderr | 17 +++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 src/test/ui/const-generics/forbid-non-structural_match-types.rs create mode 100644 src/test/ui/const-generics/forbid-non-structural_match-types.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1749fd1075e05..d6162c0bc0e9f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1532,6 +1532,17 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 3ecbf620cbc7b..5d1afcaef9140 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4978,6 +4978,30 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC. [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, +E0739: r##" +Only `structural_match` types (that is, types that derive `PartialEq` and `Eq`) +may be used as the types of const generic parameters. + +```compile_fail,E0739 +#![feature(const_generics)] + +struct A; + +struct B; // error! +``` + +To fix this example, we derive `PartialEq` and `Eq`. + +``` +#![feature(const_generics)] + +#[derive(PartialEq, Eq)] +struct A; + +struct B; // ok! +``` +"##, + ; // E0035, merged into E0087/E0089 // E0036, merged into E0087/E0089 diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.rs b/src/test/ui/const-generics/forbid-non-structural_match-types.rs new file mode 100644 index 0000000000000..7bc4f3986eb75 --- /dev/null +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.rs @@ -0,0 +1,13 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +#[derive(PartialEq, Eq)] +struct A; + +struct B; // ok + +struct C; + +struct D; //~ ERROR the types of const generic parameters must derive + +fn main() {} diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr new file mode 100644 index 0000000000000..9ab6c69521be0 --- /dev/null +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr @@ -0,0 +1,17 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/forbid-non-structural_match-types.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0739]: the types of const generic parameters must derive `PartialEq` and `Eq` + --> $DIR/forbid-non-structural_match-types.rs:11:19 + | +LL | struct D; + | ^ `C` doesn't derive both `PartialEq` and `Eq` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0739`. From 133cd2cfaf244c130e2e0d681090ca117bcba94e Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 20 Oct 2019 18:17:42 +0100 Subject: [PATCH 03/16] Search for generic parameters when finding non-`structural_match` types --- src/librustc/ty/mod.rs | 32 ++++++++++++------- src/librustc_mir/hair/pattern/mod.rs | 24 ++++++++------ src/librustc_typeck/collect.rs | 4 +-- src/librustc_typeck/error_codes.rs | 4 +-- .../forbid-non-structural_match-types.stderr | 4 +-- 5 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 77d8141c9688c..6c512a0238eed 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3393,9 +3393,15 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn_like.asyncness() } +pub enum NonStructuralMatchTy<'tcx> { + Adt(&'tcx AdtDef), + Param, +} + /// This method traverses the structure of `ty`, trying to find an /// instance of an ADT (i.e. struct or enum) that was declared without -/// the `#[structural_match]` attribute. +/// the `#[structural_match]` attribute, or a generic type parameter +/// (which cannot be determined to be `structural_match`). /// /// The "structure of a type" includes all components that would be /// considered when doing a pattern match on a constant of that @@ -3417,10 +3423,10 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { /// For more background on why Rust has this requirement, and issues /// that arose when the requirement was not enforced completely, see /// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. -pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>) - -> Option<&'tcx AdtDef> -{ +pub fn search_for_structural_match_violation<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, +) -> Option> { let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; ty.visit_with(&mut search); return search.found; @@ -3428,11 +3434,11 @@ pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, struct Search<'tcx> { tcx: TyCtxt<'tcx>, - // records the first ADT we find without `#[structural_match` - found: Option<&'tcx AdtDef>, + // Records the first ADT or type parameter we find without `#[structural_match`. + found: Option>, - // tracks ADT's previously encountered during search, so that - // we will not recur on them again. + // Tracks ADTs previously encountered during search, so that + // we will not recurse on them again. seen: FxHashSet, } @@ -3442,6 +3448,10 @@ pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, let (adt_def, substs) = match ty.kind { ty::Adt(adt_def, substs) => (adt_def, substs), + ty::Param(_) => { + self.found = Some(NonStructuralMatchTy::Param); + return true; // Stop visiting. + } ty::RawPtr(..) => { // `#[structural_match]` ignores substructure of // `*const _`/`*mut _`, so skip super_visit_with @@ -3468,9 +3478,9 @@ pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, }; if !self.tcx.has_attr(adt_def.did, sym::structural_match) { - self.found = Some(&adt_def); + self.found = Some(NonStructuralMatchTy::Adt(&adt_def)); debug!("Search found adt_def: {:?}", adt_def); - return true // Halt visiting! + return true; // Stop visiting. } if !self.seen.insert(adt_def.did) { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index d996881221857..98e286e61e942 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -999,15 +999,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if self.include_lint_checks && !saw_error { // If we were able to successfully convert the const to some pat, double-check // that the type of the const obeys `#[structural_match]` constraint. - if let Some(adt_def) = ty::search_for_adt_without_structural_match(self.tcx, cv.ty) { - - let path = self.tcx.def_path_str(adt_def.did); - let msg = format!( - "to use a constant of type `{}` in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - path, - path, - ); + if let Some(non_sm_ty) = ty::search_for_structural_match_violation(self.tcx, cv.ty) { + let msg = match non_sm_ty { + ty::NonStructuralMatchTy::Adt(adt_def) => { + let path = self.tcx.def_path_str(adt_def.did); + format!( + "to use a constant of type `{}` in a pattern, \ + `{}` must be annotated with `#[derive(PartialEq, Eq)]`", + path, + path, + ) + } + ty::NonStructuralMatchTy::Param => { + bug!("use of constant whose type is a parameter inside a pattern"); + } + }; // before issuing lint, double-check there even *is* a // semantic PartialEq for us to dispatch to. diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d6162c0bc0e9f..08fb5ae1676e7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1532,11 +1532,11 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option $DIR/forbid-non-structural_match-types.rs:11:19 | LL | struct D; @@ -14,4 +14,4 @@ LL | struct D; error: aborting due to previous error -For more information about this error, try `rustc --explain E0739`. +For more information about this error, try `rustc --explain E0740`. From f0e6cd9f89d3cdb11f417707690679fc334dfe0a Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 20 Oct 2019 18:18:24 +0100 Subject: [PATCH 04/16] Remove "type parameter depends on const parameter" error from resolution --- src/librustc_resolve/diagnostics.rs | 10 -------- src/librustc_resolve/error_codes.rs | 7 +++--- src/librustc_resolve/late.rs | 23 +------------------ src/librustc_resolve/lib.rs | 15 ++---------- ...aram-type-depends-on-type-param-ungated.rs | 2 +- ...-type-depends-on-type-param-ungated.stderr | 14 +++++------ .../const-param-type-depends-on-type-param.rs | 3 +-- ...st-param-type-depends-on-type-param.stderr | 19 ++++----------- 8 files changed, 21 insertions(+), 72 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 5647d5b2794af..7634093fbefba 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -367,16 +367,6 @@ impl<'a> Resolver<'a> { span, "`Self` in type parameter default".to_string()); err } - ResolutionError::ConstParamDependentOnTypeParam => { - let mut err = struct_span_err!( - self.session, - span, - E0671, - "const parameters cannot depend on type parameters" - ); - err.span_label(span, format!("const parameter depends on type parameter")); - err - } } } diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index b82cba8c83dc4..49f8e82a2d1b5 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1880,13 +1880,14 @@ fn main() { "##, E0671: r##" +#### Note: this error code is no longer emitted by the compiler. + Const parameters cannot depend on type parameters. The following is therefore invalid: -```compile_fail,E0671 +```compile_fail,E0740 #![feature(const_generics)] -fn const_id() -> T { // error: const parameter - // depends on type parameter +fn const_id() -> T { // error N } ``` diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 73a282b1a0ec1..136ab1f0444fa 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -111,9 +111,6 @@ crate enum RibKind<'a> { /// from the default of a type parameter because they're not declared /// before said type parameter. Also see the `visit_generics` override. ForwardTyParamBanRibKind, - - /// We forbid the use of type parameters as the types of const parameters. - TyParamAsConstParamTy, } impl RibKind<'_> { @@ -128,8 +125,7 @@ impl RibKind<'_> { | MacroDefinition(_) => false, AssocItemRibKind | ItemRibKind(_) - | ForwardTyParamBanRibKind - | TyParamAsConstParamTy => true, + | ForwardTyParamBanRibKind => true, } } } @@ -483,18 +479,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } - // We also ban access to type parameters for use as the types of const parameters. - let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy); - const_ty_param_ban_rib.bindings.extend(generics.params.iter() - .filter(|param| { - if let GenericParamKind::Type { .. } = param.kind { - true - } else { - false - } - }) - .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err))); - for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => self.visit_generic_param(param), @@ -513,15 +497,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } GenericParamKind::Const { ref ty } => { - self.ribs[TypeNS].push(const_ty_param_ban_rib); - for bound in ¶m.bounds { self.visit_param_bound(bound); } - self.visit_ty(ty); - - const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap(); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 17d8f0f211a92..1cc21a54e3cff 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -215,8 +215,6 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, // FIXME(const_generics:defaults) /// Error E0735: type parameters with a default cannot use `Self` SelfInTyParamDefault, - /// Error E0671: const parameter cannot depend on type parameter. - ConstParamDependentOnTypeParam, } // A minimal representation of a path segment. We use this in resolve because @@ -2169,15 +2167,6 @@ impl<'a> Resolver<'a> { return Res::Err; } - // An invalid use of a type parameter as the type of a const parameter. - if let TyParamAsConstParamTy = all_ribs[rib_index].kind { - if record_used { - self.report_error(span, ResolutionError::ConstParamDependentOnTypeParam); - } - assert_eq!(res, Res::Err); - return Res::Err; - } - match res { Res::Local(_) => { use ResolutionError::*; @@ -2186,7 +2175,7 @@ impl<'a> Resolver<'a> { for rib in ribs { match rib.kind { NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) | - ForwardTyParamBanRibKind | TyParamAsConstParamTy => { + ForwardTyParamBanRibKind => { // Nothing to do. Continue. } ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => { @@ -2220,7 +2209,7 @@ impl<'a> Resolver<'a> { let has_generic_params = match rib.kind { NormalRibKind | AssocItemRibKind | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind | - ConstantItemRibKind | TyParamAsConstParamTy => { + ConstantItemRibKind => { // Nothing to do. Continue. continue; } diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs index af5e8f49754e8..78bd549ba791a 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; struct B(PhantomData<[T; N]>); //~ ERROR const generics are unstable -//~^ ERROR const parameters cannot depend on type parameters +//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq` fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr index c659074a091c8..ba6f53e56840e 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -1,9 +1,3 @@ -error[E0671]: const parameters cannot depend on type parameters - --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 - | -LL | struct B(PhantomData<[T; N]>); - | ^ const parameter depends on type parameter - error[E0658]: const generics are unstable --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19 | @@ -13,7 +7,13 @@ LL | struct B(PhantomData<[T; N]>); = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable +error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` + --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 + | +LL | struct B(PhantomData<[T; N]>); + | ^ `T` doesn't derive both `PartialEq` and `Eq` + error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0671. +Some errors have detailed explanations: E0658, E0740. For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs index 28e0d6c2bb7e7..b76209571b05c 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -7,7 +7,6 @@ // details. pub struct Dependent([(); X]); -//~^ ERROR const parameters cannot depend on type parameters -//~^^ ERROR parameter `T` is never used +//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq` fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr index db14f9c9bf695..c86a09bef0b8d 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr @@ -1,9 +1,3 @@ -error[E0671]: const parameters cannot depend on type parameters - --> $DIR/const-param-type-depends-on-type-param.rs:9:34 - | -LL | pub struct Dependent([(); X]); - | ^ const parameter depends on type parameter - warning: the feature `const_generics` is incomplete and may cause the compiler to crash --> $DIR/const-param-type-depends-on-type-param.rs:1:12 | @@ -12,15 +6,12 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0392]: parameter `T` is never used - --> $DIR/const-param-type-depends-on-type-param.rs:9:22 +error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` + --> $DIR/const-param-type-depends-on-type-param.rs:9:34 | LL | pub struct Dependent([(); X]); - | ^ unused parameter - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + | ^ `T` doesn't derive both `PartialEq` and `Eq` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0392, E0671. -For more information about an error, try `rustc --explain E0392`. +For more information about this error, try `rustc --explain E0740`. From 9f788f3a2b7626318d0bdedca38986fc283f481f Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 21 Oct 2019 16:54:33 +0100 Subject: [PATCH 05/16] Fix rustdoc const generics test --- src/test/rustdoc/const-generics/const-impl.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs index 85ee6d3376b27..2d506787b3b80 100644 --- a/src/test/rustdoc/const-generics/const-impl.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -4,6 +4,7 @@ #![crate_name = "foo"] +#[derive(PartialEq, Eq)] pub enum Order { Sorted, Unsorted, From 7f13a4a80a67ecc4fd0521e867eeb91b657f2fa0 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 22 Oct 2019 12:00:54 +0100 Subject: [PATCH 06/16] Remove FIXME --- src/librustc/ty/relate.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 41f34703622e7..1da65f4b51d36 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -557,10 +557,9 @@ pub fn super_relate_consts>( x.val }; - // Currently, the values that can be unified are those that - // implement both `PartialEq` and `Eq`, corresponding to - // `structural_match` types. - // FIXME(const_generics): check for `structural_match` synthetic attribute. + // Currently, the values that can be unified are primitive types, + // and those that derive both `PartialEq` and `Eq`, corresponding + // to `structural_match` types. let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) { (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => { // The caller should handle these cases! From 2dda8ad98a8d5089335b2d09307f1bfd085499f9 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 22 Oct 2019 12:28:23 +0100 Subject: [PATCH 07/16] Use E0741 for structural match error --- src/librustc_resolve/error_codes.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/error_codes.rs | 4 ++-- .../const-param-type-depends-on-type-param-ungated.stderr | 4 ++-- .../const-param-type-depends-on-type-param.stderr | 4 ++-- .../const-generics/forbid-non-structural_match-types.stderr | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 49f8e82a2d1b5..df22085c38c74 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1884,7 +1884,7 @@ E0671: r##" Const parameters cannot depend on type parameters. The following is therefore invalid: -```compile_fail,E0740 +```compile_fail,E0741 #![feature(const_generics)] fn const_id() -> T { // error diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 08fb5ae1676e7..f40667652cac0 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1536,7 +1536,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option(PhantomData<[T; N]>); = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable -error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` +error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 | LL | struct B(PhantomData<[T; N]>); @@ -15,5 +15,5 @@ LL | struct B(PhantomData<[T; N]>); error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0740. +Some errors have detailed explanations: E0658, E0741. For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr index c86a09bef0b8d..c9d6db7e2c220 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr @@ -6,7 +6,7 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` +error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` --> $DIR/const-param-type-depends-on-type-param.rs:9:34 | LL | pub struct Dependent([(); X]); @@ -14,4 +14,4 @@ LL | pub struct Dependent([(); X]); error: aborting due to previous error -For more information about this error, try `rustc --explain E0740`. +For more information about this error, try `rustc --explain E0741`. diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr index c870d9b1db486..0fd9e0599e80e 100644 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr @@ -6,7 +6,7 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` +error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` --> $DIR/forbid-non-structural_match-types.rs:11:19 | LL | struct D; @@ -14,4 +14,4 @@ LL | struct D; error: aborting due to previous error -For more information about this error, try `rustc --explain E0740`. +For more information about this error, try `rustc --explain E0741`. From fe3dc3171066e26085ca11be77ade8c9f8adee2d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 22 Oct 2019 15:22:57 -0700 Subject: [PATCH 08/16] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 3a9abe3f06555..3ba5f27170db1 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3a9abe3f065554a7fbc59f440df2baba4a6e47ee +Subproject commit 3ba5f27170db10af7a92f2b682e049397197b8fa From 0771b89d09a660b69896238b1cfb5c75857c0efa Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 14 Oct 2019 13:13:38 +0200 Subject: [PATCH 09/16] Create new error code E0740 for visibility restrictions to ancestor module issues --- src/librustc_resolve/build_reduced_graph.rs | 6 +++--- src/librustc_resolve/error_codes.rs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index eadae52c250a5..c67850087568e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -268,9 +268,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { if self.r.is_accessible_from(vis, parent_scope.module) { vis } else { - let msg = - "visibilities can only be restricted to ancestor modules"; - self.r.session.span_err(path.span, msg); + struct_span_err!(self.r.session, path.span, E0741, + "visibilities can only be restricted to ancestor modules") + .emit(); ty::Visibility::Public } } diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 8ccb27078d569..241b630a9f8ca 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1918,4 +1918,5 @@ struct Foo> { E0576, E0577, E0578, + E0740, } From 8c08d8a29975bd4232cc1a9cc200df69eeb68a87 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 14 Oct 2019 14:06:54 +0200 Subject: [PATCH 10/16] Add long error explanation for E0740 --- src/librustc_resolve/error_codes.rs | 39 ++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 241b630a9f8ca..017a8a0c23898 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1897,6 +1897,44 @@ struct Foo> { ``` "##, +E0741: r##" +Visibility is restricted to a module which isn't an ancestor of the current +item. + +Erroneous code example: + +```compile_fail,E0741,edition2018 +pub mod Sea {} + +pub (in crate::Sea) struct Shark; // error! + +fn main() {} +``` + +To fix this error, we need to move the `Shark` struct inside the `Sea` module: + +```edition2018 +pub mod Sea { + pub (in crate::Sea) struct Shark; // ok! +} + +fn main() {} +``` + +Of course, you can do it as long as the module you're referring to is an +ancestor: + +```edition2018 +pub mod Earth { + pub mod Sea { + pub (in crate::Earth) struct Shark; // ok! + } +} + +fn main() {} +``` +"##, + ; // E0153, unused error code // E0157, unused error code @@ -1918,5 +1956,4 @@ struct Foo> { E0576, E0577, E0578, - E0740, } From b64d69d3155f688dbbc94904774698347b401857 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 14 Oct 2019 14:07:05 +0200 Subject: [PATCH 11/16] Update ui tests --- src/test/ui/privacy/restricted/relative-2018.stderr | 3 ++- src/test/ui/privacy/restricted/test.stderr | 4 ++-- src/test/ui/proc-macro/issue-50493.stderr | 5 +++-- src/test/ui/pub/pub-restricted.stderr | 5 +++-- src/test/ui/resolve/resolve-bad-visibility.stderr | 5 +++-- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/test/ui/privacy/restricted/relative-2018.stderr b/src/test/ui/privacy/restricted/relative-2018.stderr index 61effc463e98f..2205d6e518cf3 100644 --- a/src/test/ui/privacy/restricted/relative-2018.stderr +++ b/src/test/ui/privacy/restricted/relative-2018.stderr @@ -1,4 +1,4 @@ -error: visibilities can only be restricted to ancestor modules +error[E0741]: visibilities can only be restricted to ancestor modules --> $DIR/relative-2018.rs:7:12 | LL | pub(in ::core) struct S4; @@ -14,3 +14,4 @@ LL | pub(in a::b) struct S5; error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0741`. diff --git a/src/test/ui/privacy/restricted/test.stderr b/src/test/ui/privacy/restricted/test.stderr index a23973d0853f1..b39a42ef3ce3b 100644 --- a/src/test/ui/privacy/restricted/test.stderr +++ b/src/test/ui/privacy/restricted/test.stderr @@ -4,7 +4,7 @@ error[E0433]: failed to resolve: maybe a missing crate `bad`? LL | pub(in bad::path) mod m1 {} | ^^^ maybe a missing crate `bad`? -error: visibilities can only be restricted to ancestor modules +error[E0741]: visibilities can only be restricted to ancestor modules --> $DIR/test.rs:51:12 | LL | pub(in foo) mod m2 {} @@ -78,5 +78,5 @@ LL | u.h(); error: aborting due to 12 previous errors -Some errors have detailed explanations: E0364, E0433, E0603, E0616, E0624. +Some errors have detailed explanations: E0364, E0433, E0603, E0616, E0624, E0741. For more information about an error, try `rustc --explain E0364`. diff --git a/src/test/ui/proc-macro/issue-50493.stderr b/src/test/ui/proc-macro/issue-50493.stderr index 28c61a2f52fed..25035106f25c9 100644 --- a/src/test/ui/proc-macro/issue-50493.stderr +++ b/src/test/ui/proc-macro/issue-50493.stderr @@ -1,4 +1,4 @@ -error: visibilities can only be restricted to ancestor modules +error[E0741]: visibilities can only be restricted to ancestor modules --> $DIR/issue-50493.rs:8:12 | LL | pub(in restricted) field: usize, @@ -12,4 +12,5 @@ LL | #[derive(Derive)] error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0616`. +Some errors have detailed explanations: E0616, E0741. +For more information about an error, try `rustc --explain E0616`. diff --git a/src/test/ui/pub/pub-restricted.stderr b/src/test/ui/pub/pub-restricted.stderr index 596264ba16b42..3ec4e1143feba 100644 --- a/src/test/ui/pub/pub-restricted.stderr +++ b/src/test/ui/pub/pub-restricted.stderr @@ -53,7 +53,7 @@ LL | pub (xyz) fn xyz() {} `pub(super)`: visible only in the current module's parent `pub(in path::to::module)`: visible only on the specified path -error: visibilities can only be restricted to ancestor modules +error[E0741]: visibilities can only be restricted to ancestor modules --> $DIR/pub-restricted.rs:25:17 | LL | pub (in x) non_parent_invalid: usize, @@ -61,4 +61,5 @@ LL | pub (in x) non_parent_invalid: usize, error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0704`. +Some errors have detailed explanations: E0704, E0741. +For more information about an error, try `rustc --explain E0704`. diff --git a/src/test/ui/resolve/resolve-bad-visibility.stderr b/src/test/ui/resolve/resolve-bad-visibility.stderr index d2fb7c7a9e69d..b077bb81872a8 100644 --- a/src/test/ui/resolve/resolve-bad-visibility.stderr +++ b/src/test/ui/resolve/resolve-bad-visibility.stderr @@ -10,7 +10,7 @@ error[E0577]: expected module, found trait `Tr` LL | pub(in Tr) struct Z; | ^^ not a module -error: visibilities can only be restricted to ancestor modules +error[E0741]: visibilities can only be restricted to ancestor modules --> $DIR/resolve-bad-visibility.rs:6:8 | LL | pub(in std::vec) struct F; @@ -30,4 +30,5 @@ LL | pub(in too_soon) struct H; error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0433`. +Some errors have detailed explanations: E0433, E0741. +For more information about an error, try `rustc --explain E0433`. From eb6d757cb0bb2e4bd81158299a118230b099ac41 Mon Sep 17 00:00:00 2001 From: Umesh Kalappa Date: Sun, 20 Oct 2019 23:48:05 -0700 Subject: [PATCH 12/16] UI failures fix --- src/test/ui/intrinsics/intrinsic-alignment.rs | 3 ++- src/test/ui/signal-alternate-stack-cleanup.rs | 1 + src/test/ui/structs-enums/rec-align-u64.rs | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs index 6a67d04a54cf4..02e3139d29444 100644 --- a/src/test/ui/intrinsics/intrinsic-alignment.rs +++ b/src/test/ui/intrinsics/intrinsic-alignment.rs @@ -19,7 +19,8 @@ mod rusti { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris"))] + target_os = "solaris", + target_os = "vxworks"))] mod m { #[main] #[cfg(target_arch = "x86")] diff --git a/src/test/ui/signal-alternate-stack-cleanup.rs b/src/test/ui/signal-alternate-stack-cleanup.rs index 787ff51799a8a..8fef66eac8de2 100644 --- a/src/test/ui/signal-alternate-stack-cleanup.rs +++ b/src/test/ui/signal-alternate-stack-cleanup.rs @@ -7,6 +7,7 @@ // ignore-wasm32-bare no libc // ignore-windows // ignore-sgx no libc +// ignore-vxworks no SIGWINCH in user space #![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/structs-enums/rec-align-u64.rs b/src/test/ui/structs-enums/rec-align-u64.rs index c4e9e9ea5ee1a..680a690ba34e3 100644 --- a/src/test/ui/structs-enums/rec-align-u64.rs +++ b/src/test/ui/structs-enums/rec-align-u64.rs @@ -40,7 +40,8 @@ struct Outer { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris"))] + target_os = "solaris", + target_os = "vxworks"))] mod m { #[cfg(target_arch = "x86")] pub mod m { From 8467ceff22477fe567883e6fbd810e0f9e220686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 23 Oct 2019 17:32:33 -0700 Subject: [PATCH 13/16] Tweak format string error to point at arguments always Add secondary span labels with no text to make it clear when there's a mismatch bewteen the positional arguments in a format string and the arguments to the macro. This shouldn't affect experienced users, but it should make it easier for newcomers to more clearly understand how `format!()` and `println!()` are supposed to be used. ``` error: 2 positional arguments in format string, but there is 1 argument --> file8.rs:2:14 | 2 | format!("{} {}", 1); | ^^ ^^ - ``` instead of ``` error: 2 positional arguments in format string, but there is 1 argument --> file8.rs:2:14 | 2 | format!("{} {}", 1); | ^^ ^^ ``` --- src/libsyntax_ext/format.rs | 5 ++++- src/test/ui/fmt/format-string-error.rs | 2 ++ src/test/ui/fmt/format-string-error.stderr | 8 +++++++- src/test/ui/if/ifmt-bad-arg.stderr | 10 ++++++---- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 45d9f79c28fc3..37310f46f7eed 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -278,7 +278,7 @@ impl<'a, 'b> Context<'a, 'b> { /// format string. fn report_invalid_references(&self, numbered_position_args: bool) { let mut e; - let sp = if self.is_literal { + let sp = if self.is_literal { // Point at the formatting arguments. MultiSpan::from_spans(self.arg_spans.clone()) } else { MultiSpan::from_span(self.fmtsp) @@ -304,6 +304,9 @@ impl<'a, 'b> Context<'a, 'b> { self.describe_num_args(), ), ); + for arg in &self.args { // Point at the arguments that will be formatted. + e.span_label(arg.span, ""); + } } else { let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip(); // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)` diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs index cca949aab6364..691c06a2402c5 100644 --- a/src/test/ui/fmt/format-string-error.rs +++ b/src/test/ui/fmt/format-string-error.rs @@ -48,4 +48,6 @@ fn main() { "###); //~^^^ ERROR invalid format string: unmatched `}` found + println!("{} {} {}", 1, 2); + //~^ ERROR 3 positional arguments in format string, but there are 2 arguments } diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 3dc122a7399dd..32119b18774b2 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -107,5 +107,11 @@ LL | } | = note: if you intended to print `}`, you can escape it using `}}` -error: aborting due to 12 previous errors +error: 3 positional arguments in format string, but there are 2 arguments + --> $DIR/format-string-error.rs:51:15 + | +LL | println!("{} {} {}", 1, 2); + | ^^ ^^ ^^ - - + +error: aborting due to 13 previous errors diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index 336ea2254bf5a..c58cbc312335a 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -224,8 +224,9 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:78:15 | LL | println!("{} {:.*} {}", 1, 3.2, 4); - | ^^ ^^--^ ^^ --- this parameter corresponds to the precision flag - | | + | ^^ ^^--^ ^^ - --- - + | | | + | | this parameter corresponds to the precision flag | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | = note: positional arguments are zero-based @@ -235,8 +236,9 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:81:15 | LL | println!("{} {:07$.*} {}", 1, 3.2, 4); - | ^^ ^^^----^ ^^ --- this parameter corresponds to the precision flag - | | | + | ^^ ^^^----^ ^^ - --- - + | | | | + | | | this parameter corresponds to the precision flag | | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | this width flag expects an `usize` argument at position 7, but there are 3 arguments | From 18d873e8f0d10ad61a6110af28e2d1008e6acd16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 24 Oct 2019 00:37:32 -0700 Subject: [PATCH 14/16] Avoid ICE when adjusting bad self ty --- src/librustc_typeck/check/method/confirm.rs | 20 +++++-- src/test/ui/issues/issue-65611.rs | 63 +++++++++++++++++++++ src/test/ui/issues/issue-65611.stderr | 18 ++++++ 3 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issues/issue-65611.rs create mode 100644 src/test/ui/issues/issue-65611.stderr diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 9baf06be3f6b5..59636d32bc037 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -141,14 +141,24 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { /////////////////////////////////////////////////////////////////////////// // ADJUSTMENTS - fn adjust_self_ty(&mut self, - unadjusted_self_ty: Ty<'tcx>, - pick: &probe::Pick<'tcx>) - -> Ty<'tcx> { + fn adjust_self_ty( + &mut self, + unadjusted_self_ty: Ty<'tcx>, + pick: &probe::Pick<'tcx>, + ) -> Ty<'tcx> { // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various tables. let mut autoderef = self.autoderef(self.span, unadjusted_self_ty); - let (_, n) = autoderef.nth(pick.autoderefs).unwrap(); + let (_, n) = match autoderef.nth(pick.autoderefs) { + Some(n) => n, + None => { + self.tcx.sess.delay_span_bug( + syntax_pos::DUMMY_SP, + &format!("failed autoderef {}", pick.autoderefs), + ); + return self.tcx.types.err; + } + }; assert_eq!(n, pick.autoderefs); let mut adjustments = autoderef.adjust_steps(self, Needs::None); diff --git a/src/test/ui/issues/issue-65611.rs b/src/test/ui/issues/issue-65611.rs new file mode 100644 index 0000000000000..b74ee1b0c6e54 --- /dev/null +++ b/src/test/ui/issues/issue-65611.rs @@ -0,0 +1,63 @@ +use std::mem::MaybeUninit; +use std::ops::Deref; + +pub unsafe trait Array { + /// The array’s element type + type Item; + #[doc(hidden)] + /// The smallest index type that indexes the array. + type Index: Index; + #[doc(hidden)] + fn as_ptr(&self) -> *const Self::Item; + #[doc(hidden)] + fn as_mut_ptr(&mut self) -> *mut Self::Item; + #[doc(hidden)] + fn capacity() -> usize; +} + +pub trait Index : PartialEq + Copy { + fn to_usize(self) -> usize; + fn from(usize) -> Self; +} + +impl Index for usize { + fn to_usize(self) -> usize { self } + fn from(val: usize) -> Self { + val + } +} + +unsafe impl Array for [T; 1] { + type Item = T; + type Index = usize; + fn as_ptr(&self) -> *const T { self as *const _ as *const _ } + fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _} + fn capacity() -> usize { 1 } +} + +impl Deref for ArrayVec { + type Target = [A::Item]; + #[inline] + fn deref(&self) -> &[A::Item] { + panic!() + } +} + +pub struct ArrayVec { + xs: MaybeUninit, + len: usize, +} + +impl ArrayVec { + pub fn new() -> ArrayVec { + panic!() + } +} + +fn main() { + let mut buffer = ArrayVec::new(); + let x = buffer.last().unwrap().0.clone(); + //~^ ERROR type annotations needed + //~| ERROR no field `0` on type `&_` + buffer.reverse(); +} diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/issues/issue-65611.stderr new file mode 100644 index 0000000000000..cb441c13c6b9e --- /dev/null +++ b/src/test/ui/issues/issue-65611.stderr @@ -0,0 +1,18 @@ +error[E0282]: type annotations needed + --> $DIR/issue-65611.rs:59:20 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^^^^ cannot infer type for `T` + | + = note: type must be known at this point + +error[E0609]: no field `0` on type `&_` + --> $DIR/issue-65611.rs:59:36 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0609. +For more information about an error, try `rustc --explain E0282`. From 060b6cbe74f65b8d517c4d4936f4a361f3e4287d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 24 Oct 2019 08:07:03 -0700 Subject: [PATCH 15/16] Update hashbrown to 0.6.2 Pulls in rust-lang/hashbrown#119 which should be a good improvement for compile times of hashmap-heavy crates. --- Cargo.lock | 6 +++--- src/libstd/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index efcbd7b6794f0..fb81c0637cca9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1297,9 +1297,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" +checksum = "3cd9867f119b19fecb08cd5c326ad4488d7a1da4bf75b4d95d71db742525aaab" dependencies = [ "autocfg", "compiler_builtins", @@ -4146,7 +4146,7 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.6.1", + "hashbrown 0.6.2", "libc", "panic_abort", "panic_unwind", diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 5309af6f4c342..efe5c9d28f0d2 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,7 +23,7 @@ libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of compiler_builtins = { version = "0.1.16" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } -hashbrown = { version = "0.6.1", default-features = false, features = ['rustc-dep-of-std'] } +hashbrown = { version = "0.6.2", default-features = false, features = ['rustc-dep-of-std'] } [dependencies.backtrace_rs] package = "backtrace" From 184a61f0bfa4cf6c913d03be3da019ef3e7402cd Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 24 Oct 2019 14:25:23 +0800 Subject: [PATCH 16/16] Don't assert for different instance on impl trait alias --- src/librustc_typeck/check/mod.rs | 3 +-- ...issue-65679-inst-opaque-ty-from-val-twice.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 73a025182a7e3..790407aae9ff1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2761,8 +2761,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut opaque_types = self.opaque_types.borrow_mut(); for (ty, decl) in opaque_type_map { - let old_value = opaque_types.insert(ty, decl); - assert!(old_value.is_none(), "instantiated twice: {:?}/{:?}", ty, decl); + let _ = opaque_types.insert(ty, decl); } value diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs new file mode 100644 index 0000000000000..12eb75ae4c019 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type T = impl Sized; +// The concrete type referred by impl-trait-type-alias(`T`) is guaranteed +// to be the same as where it occurs, whereas `impl Trait`'s instance is location sensitive; +// so difference assertion should not be declared on impl-trait-type-alias's instances. +// for details, check RFC-2515: +// https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md + +fn take(_: fn() -> T) {} + +fn main() { + take(|| {}); + take(|| {}); +}