From 3dca17e62def01ee8c8621db7925d55f9275f6d9 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jul 2019 13:33:51 +0100 Subject: Disallow duplicate lifetime parameters with legacy hygiene They were resolved with modern hygiene, making this just a strange way to shadow lifetimes. --- src/test/ui/hygiene/duplicate_lifetimes.rs | 19 ++++++++++++++++++ src/test/ui/hygiene/duplicate_lifetimes.stderr | 27 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/test/ui/hygiene/duplicate_lifetimes.rs create mode 100644 src/test/ui/hygiene/duplicate_lifetimes.stderr (limited to 'src/test') diff --git a/src/test/ui/hygiene/duplicate_lifetimes.rs b/src/test/ui/hygiene/duplicate_lifetimes.rs new file mode 100644 index 00000000000..e7312b51dbc --- /dev/null +++ b/src/test/ui/hygiene/duplicate_lifetimes.rs @@ -0,0 +1,19 @@ +// Ensure that lifetime parameter names are modernized before we check for +// duplicates. + +#![feature(decl_macro, rustc_attrs)] + +#[rustc_macro_transparency = "semitransparent"] +macro m($a:lifetime) { + fn g<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice +} + +#[rustc_macro_transparency = "transparent"] +macro n($a:lifetime) { + fn h<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice +} + +m!('a); +n!('a); + +fn main() {} diff --git a/src/test/ui/hygiene/duplicate_lifetimes.stderr b/src/test/ui/hygiene/duplicate_lifetimes.stderr new file mode 100644 index 00000000000..7aaea6ff24e --- /dev/null +++ b/src/test/ui/hygiene/duplicate_lifetimes.stderr @@ -0,0 +1,27 @@ +error[E0263]: lifetime name `'a` declared twice in the same scope + --> $DIR/duplicate_lifetimes.rs:8:14 + | +LL | fn g<$a, 'a>() {} + | ^^ declared twice +... +LL | m!('a); + | ------- + | | | + | | previous declaration here + | in this macro invocation + +error[E0263]: lifetime name `'a` declared twice in the same scope + --> $DIR/duplicate_lifetimes.rs:13:14 + | +LL | fn h<$a, 'a>() {} + | ^^ declared twice +... +LL | n!('a); + | ------- + | | | + | | previous declaration here + | in this macro invocation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0263`. -- cgit 1.4.1-3-g733a5 From 8876b3b9b0bf652cddf68d9ddcb5b5fa31d829ab Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jul 2019 13:34:03 +0100 Subject: Resolve const parameters with modern hygiene Declarations were already modernized, resulting in cases where a macro couldn't resolve it's own identifier. --- src/librustc_resolve/lib.rs | 26 +++++--- src/test/ui/hygiene/generic_params.rs | 104 ++++++++++++++++++++++++++++++ src/test/ui/hygiene/generic_params.stderr | 6 ++ src/test/ui/hygiene/ty_params.rs | 14 ---- 4 files changed, 128 insertions(+), 22 deletions(-) create mode 100644 src/test/ui/hygiene/generic_params.rs create mode 100644 src/test/ui/hygiene/generic_params.stderr delete mode 100644 src/test/ui/hygiene/ty_params.rs (limited to 'src/test') diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a5e498fa756..8884d1cd27f 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -872,8 +872,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { debug!("(resolving function) entering function"); let rib_kind = match function_kind { FnKind::ItemFn(..) => FnItemRibKind, - FnKind::Method(..) => AssocItemRibKind, - FnKind::Closure(_) => NormalRibKind, + FnKind::Method(..) | FnKind::Closure(_) => NormalRibKind, }; // Create a value rib for the function. @@ -2310,21 +2309,32 @@ impl<'a> Resolver<'a> { if ident.name == kw::Invalid { return Some(LexicalScopeBinding::Res(Res::Err)); } - ident.span = if ident.name == kw::SelfUpper { + let (general_span, modern_span) = if ident.name == kw::SelfUpper { // FIXME(jseyfried) improve `Self` hygiene - ident.span.with_ctxt(SyntaxContext::empty()) + let empty_span = ident.span.with_ctxt(SyntaxContext::empty()); + (empty_span, empty_span) } else if ns == TypeNS { - ident.span.modern() + let modern_span = ident.span.modern(); + (modern_span, modern_span) } else { - ident.span.modern_and_legacy() + (ident.span.modern_and_legacy(), ident.span.modern()) }; + ident.span = general_span; + let modern_ident = Ident { span: modern_span, ..ident }; // Walk backwards up the ribs in scope. let record_used = record_used_id.is_some(); let mut module = self.graph_root; for i in (0 .. self.ribs[ns].len()).rev() { debug!("walk rib\n{:?}", self.ribs[ns][i].bindings); - if let Some(res) = self.ribs[ns][i].bindings.get(&ident).cloned() { + // Use the rib kind to determine whether we are resolving parameters + // (modern hygiene) or local variables (legacy hygiene). + let rib_ident = if let AssocItemRibKind | ItemRibKind = self.ribs[ns][i].kind { + modern_ident + } else { + ident + }; + if let Some(res) = self.ribs[ns][i].bindings.get(&rib_ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::Res( self.validate_res_from_ribs(ns, i, res, record_used, path_span), @@ -2360,7 +2370,7 @@ impl<'a> Resolver<'a> { } } - ident.span = ident.span.modern(); + ident = modern_ident; let mut poisoned = None; loop { let opt_module = if let Some(node_id) = record_used_id { diff --git a/src/test/ui/hygiene/generic_params.rs b/src/test/ui/hygiene/generic_params.rs new file mode 100644 index 00000000000..9dc5adfce47 --- /dev/null +++ b/src/test/ui/hygiene/generic_params.rs @@ -0,0 +1,104 @@ +// Ensure that generic parameters always have modern hygiene. + +// check-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro, rustc_attrs, const_generics)] + +mod type_params { + macro m($T:ident) { + fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) { + (t1.clone(), t2 == t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($T:ident) { + fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + fn h(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($T:ident) { + fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + fn k(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + } + + m!(T); + n!(T); + p!(T); +} + +mod lifetime_params { + macro m($a:lifetime) { + fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($a:lifetime) { + fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($a:lifetime) { + fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + } + + m!('a); + n!('a); + p!('a); +} + +mod const_params { + macro m($C:ident) { + fn f(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($C:ident) { + fn g(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + fn h(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($C:ident) { + fn j(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + fn k(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + } + + m!(C); + n!(C); + p!(C); +} + +fn main() {} diff --git a/src/test/ui/hygiene/generic_params.stderr b/src/test/ui/hygiene/generic_params.stderr new file mode 100644 index 00000000000..ecd228a5db5 --- /dev/null +++ b/src/test/ui/hygiene/generic_params.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/generic_params.rs:6:37 + | +LL | #![feature(decl_macro, rustc_attrs, const_generics)] + | ^^^^^^^^^^^^^^ + diff --git a/src/test/ui/hygiene/ty_params.rs b/src/test/ui/hygiene/ty_params.rs deleted file mode 100644 index b296bfe5988..00000000000 --- a/src/test/ui/hygiene/ty_params.rs +++ /dev/null @@ -1,14 +0,0 @@ -// check-pass -// ignore-pretty pretty-printing is unhygienic - -#![feature(decl_macro)] - -macro m($T:ident) { - fn f(t: T, t2: $T) -> (T, $T) { - (t, t2) - } -} - -m!(T); - -fn main() {} -- cgit 1.4.1-3-g733a5 From dfad725be540137e0bc3022fe5341378e4690b9b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 24 Jul 2019 10:26:32 +0200 Subject: Recover 'for ( $pat in $expr ) $block'. --- src/libsyntax/parse/diagnostics.rs | 44 ++++++++++++++++++++++ src/libsyntax/parse/parser.rs | 11 ++++++ .../parser/recover-for-loop-parens-around-head.rs | 15 ++++++++ .../recover-for-loop-parens-around-head.stderr | 27 +++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 src/test/ui/parser/recover-for-loop-parens-around-head.rs create mode 100644 src/test/ui/parser/recover-for-loop-parens-around-head.stderr (limited to 'src/test') diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index f4fc87506f3..e9dcfa81343 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -923,6 +923,50 @@ impl<'a> Parser<'a> { } } + /// Recover a situation like `for ( $pat in $expr )` + /// and suggest writing `for $pat in $expr` instead. + /// + /// This should be called before parsing the `$block`. + crate fn recover_parens_around_for_head( + &mut self, + pat: P, + expr: &Expr, + begin_paren: Option, + ) -> P { + match (&self.token.kind, begin_paren) { + (token::CloseDelim(token::Paren), Some(begin_par_sp)) => { + self.bump(); + + let pat_str = self + .sess + .source_map() + // Remove the `(` from the span of the pattern: + .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap()) + .unwrap_or_else(|_| pprust::pat_to_string(&pat)); + + self.struct_span_err(self.prev_span, "unexpected closing `)`") + .span_label(begin_par_sp, "opening `(`") + .span_suggestion( + begin_par_sp.to(self.prev_span), + "remove parenthesis in `for` loop", + format!("{} in {}", pat_str, pprust::expr_to_string(&expr)), + // With e.g. `for (x) in y)` this would replace `(x) in y)` + // with `x) in y)` which is syntactically invalid. + // However, this is prevented before we get here. + Applicability::MachineApplicable, + ) + .emit(); + + // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint. + pat.and_then(|pat| match pat.node { + PatKind::Paren(pat) => pat, + _ => P(pat), + }) + } + _ => pat, + } + } + crate fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool { self.token.is_ident() && if let ast::ExprKind::Path(..) = node { true } else { false } && diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8f8ed411180..42030acf9df 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3275,6 +3275,14 @@ impl<'a> Parser<'a> { mut attrs: ThinVec) -> PResult<'a, P> { // Parse: `for in ` + // Record whether we are about to parse `for (`. + // This is used below for recovery in case of `for ( $stuff ) $block` + // in which case we will suggest `for $stuff $block`. + let begin_paren = match self.token.kind { + token::OpenDelim(token::Paren) => Some(self.token.span), + _ => None, + }; + let pat = self.parse_top_level_pat()?; if !self.eat_keyword(kw::In) { let in_span = self.prev_span.between(self.token.span); @@ -3290,6 +3298,9 @@ impl<'a> Parser<'a> { let in_span = self.prev_span; self.check_for_for_in_in_typo(in_span); let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; + + let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren); + let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.rs b/src/test/ui/parser/recover-for-loop-parens-around-head.rs new file mode 100644 index 00000000000..e6c59fcf22d --- /dev/null +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.rs @@ -0,0 +1,15 @@ +// Here we test that the parser is able to recover in a situation like +// `for ( $pat in $expr )` since that is familiar syntax in other languages. +// Instead we suggest that the user writes `for $pat in $expr`. + +#![deny(unused)] // Make sure we don't trigger `unused_parens`. + +fn main() { + let vec = vec![1, 2, 3]; + + for ( elem in vec ) { + //~^ ERROR expected one of `)`, `,`, or `@`, found `in` + //~| ERROR unexpected closing `)` + const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types + } +} diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr new file mode 100644 index 00000000000..c160e646c28 --- /dev/null +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr @@ -0,0 +1,27 @@ +error: expected one of `)`, `,`, or `@`, found `in` + --> $DIR/recover-for-loop-parens-around-head.rs:10:16 + | +LL | for ( elem in vec ) { + | ^^ expected one of `)`, `,`, or `@` here + +error: unexpected closing `)` + --> $DIR/recover-for-loop-parens-around-head.rs:10:23 + | +LL | for ( elem in vec ) { + | --------------^ + | | + | opening `(` + | help: remove parenthesis in `for` loop: `elem in vec` + +error[E0308]: mismatched types + --> $DIR/recover-for-loop-parens-around-head.rs:13:38 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. -- cgit 1.4.1-3-g733a5 From 18bf9dd4b7e9834bc6981ee413f025f3b2f7e386 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sun, 28 Jul 2019 17:57:04 -0400 Subject: Properly check the defining scope of existential types Fixes #52632 Existential types (soon to be 'impl trait' aliases) can either be delcared at a top-level crate/module scope, or within another item such as an fn. Previously, we were handling the second case incorrectly when recursively searching for defining usages - we would check children of the item, but not the item itself. This lead to us missing closures that consituted a defining use of the existential type, as their opaque type instantiations are stored in the TypeckTables of their parent function. This commit ensures that we explicitly visit the defining item itself, not just its children. --- src/librustc/infer/opaque_types/mod.rs | 15 +++++++++------ src/librustc_typeck/collect.rs | 21 ++++++++++++++++++--- src/test/ui/existential-type/issue-52843.rs | 11 +++++++++++ src/test/ui/existential-type/issue-52843.stderr | 20 ++++++++++++++++++++ 4 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/existential-type/issue-52843.rs create mode 100644 src/test/ui/existential-type/issue-52843.stderr (limited to 'src/test') diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 5acc3fd2fbc..73a76ebcb74 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -1189,11 +1189,7 @@ pub fn may_define_existential_type( opaque_hir_id: hir::HirId, ) -> bool { let mut hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - trace!( - "may_define_existential_type(def={:?}, opaque_node={:?})", - tcx.hir().get(hir_id), - tcx.hir().get(opaque_hir_id) - ); + // Named existential types can be defined by any siblings or children of siblings. let scope = tcx.hir().get_defining_scope(opaque_hir_id).expect("could not get defining scope"); @@ -1202,5 +1198,12 @@ pub fn may_define_existential_type( hir_id = tcx.hir().get_parent_item(hir_id); } // Syntactically, we are allowed to define the concrete type if: - hir_id == scope + let res = hir_id == scope; + trace!( + "may_define_existential_type(def={:?}, opaque_node={:?}) = {}", + tcx.hir().get(hir_id), + tcx.hir().get(opaque_hir_id), + res + ); + res } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 053ef1f8f82..0f0cbd5d76b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1664,6 +1664,7 @@ fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { intravisit::NestedVisitorMap::All(&self.tcx.hir()) } fn visit_item(&mut self, it: &'tcx Item) { + debug!("find_existential_constraints: visiting {:?}", it); let def_id = self.tcx.hir().local_def_id(it.hir_id); // The existential type itself or its children are not within its reveal scope. if def_id != self.def_id { @@ -1672,6 +1673,7 @@ fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } fn visit_impl_item(&mut self, it: &'tcx ImplItem) { + debug!("find_existential_constraints: visiting {:?}", it); let def_id = self.tcx.hir().local_def_id(it.hir_id); // The existential type itself or its children are not within its reveal scope. if def_id != self.def_id { @@ -1680,6 +1682,7 @@ fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } fn visit_trait_item(&mut self, it: &'tcx TraitItem) { + debug!("find_existential_constraints: visiting {:?}", it); let def_id = self.tcx.hir().local_def_id(it.hir_id); self.check(def_id); intravisit::walk_trait_item(self, it); @@ -1703,9 +1706,21 @@ fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } else { debug!("find_existential_constraints: scope={:?}", tcx.hir().get(scope)); match tcx.hir().get(scope) { - Node::Item(ref it) => intravisit::walk_item(&mut locator, it), - Node::ImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it), - Node::TraitItem(ref it) => intravisit::walk_trait_item(&mut locator, it), + // We explicitly call 'visit_*' methods, instead of using intravisit::walk_* methods + // This allows our visitor to process the defining item itself, causing + // it to pick up any 'sibling' defining uses. + // + // For example, this code: + // fn foo() { + // existential type Blah: Debug; + // let my_closure = || -> Blah { true }; + // } + // + // requires us to explicitly process 'foo()' in order + // to notice the defining usage of 'Blah' + Node::Item(ref it) => locator.visit_item(it), + Node::ImplItem(ref it) => locator.visit_impl_item(it), + Node::TraitItem(ref it) => locator.visit_trait_item(it), other => bug!( "{:?} is not a valid scope for an existential type item", other diff --git a/src/test/ui/existential-type/issue-52843.rs b/src/test/ui/existential-type/issue-52843.rs new file mode 100644 index 00000000000..c625909e478 --- /dev/null +++ b/src/test/ui/existential-type/issue-52843.rs @@ -0,0 +1,11 @@ +#![feature(existential_type)] + +use std::fmt::Debug; + +fn main() { + existential type Existential: Debug; + fn _unused() -> Existential { String::new() } + //~^ ERROR: concrete type differs from previous defining existential type use + let null = || -> Existential { 0 }; + println!("{:?}", null()); +} diff --git a/src/test/ui/existential-type/issue-52843.stderr b/src/test/ui/existential-type/issue-52843.stderr new file mode 100644 index 00000000000..337e84bb8f5 --- /dev/null +++ b/src/test/ui/existential-type/issue-52843.stderr @@ -0,0 +1,20 @@ +error: concrete type differs from previous defining existential type use + --> $DIR/issue-52843.rs:7:5 + | +LL | fn _unused() -> Existential { String::new() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `std::string::String` + | +note: previous use here + --> $DIR/issue-52843.rs:5:1 + | +LL | / fn main() { +LL | | existential type Existential: Debug; +LL | | fn _unused() -> Existential { String::new() } +LL | | +LL | | let null = || -> Existential { 0 }; +LL | | println!("{:?}", null()); +LL | | } + | |_^ + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 3e98c3acf5c598ae577428fa8fbf1c29e270739b Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sun, 28 Jul 2019 19:12:04 -0400 Subject: Rename test and add comment --- .../issue-52843-closure-constrain.rs | 12 ++++++++++++ .../issue-52843-closure-constrain.stderr | 20 ++++++++++++++++++++ src/test/ui/existential-type/issue-52843.rs | 11 ----------- src/test/ui/existential-type/issue-52843.stderr | 20 -------------------- 4 files changed, 32 insertions(+), 31 deletions(-) create mode 100644 src/test/ui/existential-type/issue-52843-closure-constrain.rs create mode 100644 src/test/ui/existential-type/issue-52843-closure-constrain.stderr delete mode 100644 src/test/ui/existential-type/issue-52843.rs delete mode 100644 src/test/ui/existential-type/issue-52843.stderr (limited to 'src/test') diff --git a/src/test/ui/existential-type/issue-52843-closure-constrain.rs b/src/test/ui/existential-type/issue-52843-closure-constrain.rs new file mode 100644 index 00000000000..b2bbc1f1549 --- /dev/null +++ b/src/test/ui/existential-type/issue-52843-closure-constrain.rs @@ -0,0 +1,12 @@ +// Checks to ensure that we properly detect when a closure constrains an existential type +#![feature(existential_type)] + +use std::fmt::Debug; + +fn main() { + existential type Existential: Debug; + fn _unused() -> Existential { String::new() } + //~^ ERROR: concrete type differs from previous defining existential type use + let null = || -> Existential { 0 }; + println!("{:?}", null()); +} diff --git a/src/test/ui/existential-type/issue-52843-closure-constrain.stderr b/src/test/ui/existential-type/issue-52843-closure-constrain.stderr new file mode 100644 index 00000000000..424d65a193c --- /dev/null +++ b/src/test/ui/existential-type/issue-52843-closure-constrain.stderr @@ -0,0 +1,20 @@ +error: concrete type differs from previous defining existential type use + --> $DIR/issue-52843-closure-constrain.rs:8:5 + | +LL | fn _unused() -> Existential { String::new() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `std::string::String` + | +note: previous use here + --> $DIR/issue-52843-closure-constrain.rs:6:1 + | +LL | / fn main() { +LL | | existential type Existential: Debug; +LL | | fn _unused() -> Existential { String::new() } +LL | | +LL | | let null = || -> Existential { 0 }; +LL | | println!("{:?}", null()); +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/existential-type/issue-52843.rs b/src/test/ui/existential-type/issue-52843.rs deleted file mode 100644 index c625909e478..00000000000 --- a/src/test/ui/existential-type/issue-52843.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(existential_type)] - -use std::fmt::Debug; - -fn main() { - existential type Existential: Debug; - fn _unused() -> Existential { String::new() } - //~^ ERROR: concrete type differs from previous defining existential type use - let null = || -> Existential { 0 }; - println!("{:?}", null()); -} diff --git a/src/test/ui/existential-type/issue-52843.stderr b/src/test/ui/existential-type/issue-52843.stderr deleted file mode 100644 index 337e84bb8f5..00000000000 --- a/src/test/ui/existential-type/issue-52843.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: concrete type differs from previous defining existential type use - --> $DIR/issue-52843.rs:7:5 - | -LL | fn _unused() -> Existential { String::new() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `std::string::String` - | -note: previous use here - --> $DIR/issue-52843.rs:5:1 - | -LL | / fn main() { -LL | | existential type Existential: Debug; -LL | | fn _unused() -> Existential { String::new() } -LL | | -LL | | let null = || -> Existential { 0 }; -LL | | println!("{:?}", null()); -LL | | } - | |_^ - -error: aborting due to previous error - -- cgit 1.4.1-3-g733a5 From e2ee2a3854c48bdea781683070d150c533b5803b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 29 Jul 2019 03:27:46 +0200 Subject: Move ui/{existential-type -> existential_types}. --- src/test/ui/existential-type/issue-58887.rs | 23 ------------------ src/test/ui/existential-type/issue-58887.stderr | 30 ------------------------ src/test/ui/existential-type/issue-60371.rs | 15 ------------ src/test/ui/existential-type/issue-60371.stderr | 29 ----------------------- src/test/ui/existential_types/issue-58887.rs | 23 ++++++++++++++++++ src/test/ui/existential_types/issue-58887.stderr | 30 ++++++++++++++++++++++++ src/test/ui/existential_types/issue-60371.rs | 15 ++++++++++++ src/test/ui/existential_types/issue-60371.stderr | 29 +++++++++++++++++++++++ 8 files changed, 97 insertions(+), 97 deletions(-) delete mode 100644 src/test/ui/existential-type/issue-58887.rs delete mode 100644 src/test/ui/existential-type/issue-58887.stderr delete mode 100644 src/test/ui/existential-type/issue-60371.rs delete mode 100644 src/test/ui/existential-type/issue-60371.stderr create mode 100644 src/test/ui/existential_types/issue-58887.rs create mode 100644 src/test/ui/existential_types/issue-58887.stderr create mode 100644 src/test/ui/existential_types/issue-60371.rs create mode 100644 src/test/ui/existential_types/issue-60371.stderr (limited to 'src/test') diff --git a/src/test/ui/existential-type/issue-58887.rs b/src/test/ui/existential-type/issue-58887.rs deleted file mode 100644 index f038648ec21..00000000000 --- a/src/test/ui/existential-type/issue-58887.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![feature(existential_type)] - -trait UnwrapItemsExt { - type Iter; - fn unwrap_items(self) -> Self::Iter; -} - -impl UnwrapItemsExt for I -where - I: Iterator>, - E: std::fmt::Debug, -{ - existential type Iter: Iterator; - //~^ ERROR: could not find defining uses - - fn unwrap_items(self) -> Self::Iter { - //~^ ERROR: type parameter `T` is part of concrete type - //~| ERROR: type parameter `E` is part of concrete type - self.map(|x| x.unwrap()) - } -} - -fn main() {} diff --git a/src/test/ui/existential-type/issue-58887.stderr b/src/test/ui/existential-type/issue-58887.stderr deleted file mode 100644 index 800f4b7e059..00000000000 --- a/src/test/ui/existential-type/issue-58887.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error: type parameter `T` is part of concrete type but not used in parameter list for existential type - --> $DIR/issue-58887.rs:16:41 - | -LL | fn unwrap_items(self) -> Self::Iter { - | _________________________________________^ -LL | | -LL | | -LL | | self.map(|x| x.unwrap()) -LL | | } - | |_____^ - -error: type parameter `E` is part of concrete type but not used in parameter list for existential type - --> $DIR/issue-58887.rs:16:41 - | -LL | fn unwrap_items(self) -> Self::Iter { - | _________________________________________^ -LL | | -LL | | -LL | | self.map(|x| x.unwrap()) -LL | | } - | |_____^ - -error: could not find defining uses - --> $DIR/issue-58887.rs:13:5 - | -LL | existential type Iter: Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/existential-type/issue-60371.rs b/src/test/ui/existential-type/issue-60371.rs deleted file mode 100644 index f9def11d193..00000000000 --- a/src/test/ui/existential-type/issue-60371.rs +++ /dev/null @@ -1,15 +0,0 @@ -trait Bug { - type Item: Bug; - - const FUN: fn() -> Self::Item; -} - -impl Bug for &() { - existential type Item: Bug; //~ ERROR existential types are unstable - //~^ ERROR the trait bound `(): Bug` is not satisfied - //~^^ ERROR could not find defining uses - - const FUN: fn() -> Self::Item = || (); -} - -fn main() {} diff --git a/src/test/ui/existential-type/issue-60371.stderr b/src/test/ui/existential-type/issue-60371.stderr deleted file mode 100644 index 092cb31f97d..00000000000 --- a/src/test/ui/existential-type/issue-60371.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0658]: existential types are unstable - --> $DIR/issue-60371.rs:8:5 - | -LL | existential type Item: Bug; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/63063 - = help: add `#![feature(existential_type)]` to the crate attributes to enable - -error[E0277]: the trait bound `(): Bug` is not satisfied - --> $DIR/issue-60371.rs:8:5 - | -LL | existential type Item: Bug; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bug` is not implemented for `()` - | - = help: the following implementations were found: - <&() as Bug> - = note: the return type of a function must have a statically known size - -error: could not find defining uses - --> $DIR/issue-60371.rs:8:5 - | -LL | existential type Item: Bug; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0277, E0658. -For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/existential_types/issue-58887.rs b/src/test/ui/existential_types/issue-58887.rs new file mode 100644 index 00000000000..f038648ec21 --- /dev/null +++ b/src/test/ui/existential_types/issue-58887.rs @@ -0,0 +1,23 @@ +#![feature(existential_type)] + +trait UnwrapItemsExt { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +impl UnwrapItemsExt for I +where + I: Iterator>, + E: std::fmt::Debug, +{ + existential type Iter: Iterator; + //~^ ERROR: could not find defining uses + + fn unwrap_items(self) -> Self::Iter { + //~^ ERROR: type parameter `T` is part of concrete type + //~| ERROR: type parameter `E` is part of concrete type + self.map(|x| x.unwrap()) + } +} + +fn main() {} diff --git a/src/test/ui/existential_types/issue-58887.stderr b/src/test/ui/existential_types/issue-58887.stderr new file mode 100644 index 00000000000..800f4b7e059 --- /dev/null +++ b/src/test/ui/existential_types/issue-58887.stderr @@ -0,0 +1,30 @@ +error: type parameter `T` is part of concrete type but not used in parameter list for existential type + --> $DIR/issue-58887.rs:16:41 + | +LL | fn unwrap_items(self) -> Self::Iter { + | _________________________________________^ +LL | | +LL | | +LL | | self.map(|x| x.unwrap()) +LL | | } + | |_____^ + +error: type parameter `E` is part of concrete type but not used in parameter list for existential type + --> $DIR/issue-58887.rs:16:41 + | +LL | fn unwrap_items(self) -> Self::Iter { + | _________________________________________^ +LL | | +LL | | +LL | | self.map(|x| x.unwrap()) +LL | | } + | |_____^ + +error: could not find defining uses + --> $DIR/issue-58887.rs:13:5 + | +LL | existential type Iter: Iterator; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/existential_types/issue-60371.rs b/src/test/ui/existential_types/issue-60371.rs new file mode 100644 index 00000000000..f9def11d193 --- /dev/null +++ b/src/test/ui/existential_types/issue-60371.rs @@ -0,0 +1,15 @@ +trait Bug { + type Item: Bug; + + const FUN: fn() -> Self::Item; +} + +impl Bug for &() { + existential type Item: Bug; //~ ERROR existential types are unstable + //~^ ERROR the trait bound `(): Bug` is not satisfied + //~^^ ERROR could not find defining uses + + const FUN: fn() -> Self::Item = || (); +} + +fn main() {} diff --git a/src/test/ui/existential_types/issue-60371.stderr b/src/test/ui/existential_types/issue-60371.stderr new file mode 100644 index 00000000000..092cb31f97d --- /dev/null +++ b/src/test/ui/existential_types/issue-60371.stderr @@ -0,0 +1,29 @@ +error[E0658]: existential types are unstable + --> $DIR/issue-60371.rs:8:5 + | +LL | existential type Item: Bug; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/63063 + = help: add `#![feature(existential_type)]` to the crate attributes to enable + +error[E0277]: the trait bound `(): Bug` is not satisfied + --> $DIR/issue-60371.rs:8:5 + | +LL | existential type Item: Bug; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bug` is not implemented for `()` + | + = help: the following implementations were found: + <&() as Bug> + = note: the return type of a function must have a statically known size + +error: could not find defining uses + --> $DIR/issue-60371.rs:8:5 + | +LL | existential type Item: Bug; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. -- cgit 1.4.1-3-g733a5 From b2a5d99705e2b93462669791f9a2bf0bd0055384 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 29 Jul 2019 03:38:49 +0200 Subject: Move ui/existential_type.rs -> ui/existential_type/existential_type-pass. --- src/test/ui/existential_type.rs | 89 ---------------------- .../ui/existential_types/existential_type-pass.rs | 89 ++++++++++++++++++++++ 2 files changed, 89 insertions(+), 89 deletions(-) delete mode 100644 src/test/ui/existential_type.rs create mode 100644 src/test/ui/existential_types/existential_type-pass.rs (limited to 'src/test') diff --git a/src/test/ui/existential_type.rs b/src/test/ui/existential_type.rs deleted file mode 100644 index c2cf0eeed3d..00000000000 --- a/src/test/ui/existential_type.rs +++ /dev/null @@ -1,89 +0,0 @@ -// run-pass - -#![allow(dead_code)] -#![allow(unused_assignments)] -#![allow(unused_variables)] -#![feature(existential_type)] - -fn main() { - assert_eq!(foo().to_string(), "foo"); - assert_eq!(bar1().to_string(), "bar1"); - assert_eq!(bar2().to_string(), "bar2"); - let mut x = bar1(); - x = bar2(); - assert_eq!(boo::boo().to_string(), "boo"); - assert_eq!(my_iter(42u8).collect::>(), vec![42u8]); -} - -// single definition -existential type Foo: std::fmt::Display; - -fn foo() -> Foo { - "foo" -} - -// two definitions -existential type Bar: std::fmt::Display; - -fn bar1() -> Bar { - "bar1" -} - -fn bar2() -> Bar { - "bar2" -} - -// definition in submodule -existential type Boo: std::fmt::Display; - -mod boo { - pub fn boo() -> super::Boo { - "boo" - } -} - -existential type MyIter: Iterator; - -fn my_iter(t: T) -> MyIter { - std::iter::once(t) -} - -fn my_iter2(t: T) -> MyIter { - std::iter::once(t) -} - -// param names should not have an effect! -fn my_iter3(u: U) -> MyIter { - std::iter::once(u) -} - -// param position should not have an effect! -fn my_iter4(_: U, v: V) -> MyIter { - std::iter::once(v) -} - -// param names should not have an effect! -existential type MyOtherIter: Iterator; - -fn my_other_iter(u: U) -> MyOtherIter { - std::iter::once(u) -} - -trait Trait {} -existential type GenericBound<'a, T: Trait>: Sized + 'a; - -fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> { - t -} - -mod pass_through { - pub existential type Passthrough: Sized + 'static; - - fn define_passthrough(t: T) -> Passthrough { - t - } -} - -fn use_passthrough(x: pass_through::Passthrough) -> pass_through::Passthrough { - x -} diff --git a/src/test/ui/existential_types/existential_type-pass.rs b/src/test/ui/existential_types/existential_type-pass.rs new file mode 100644 index 00000000000..c2cf0eeed3d --- /dev/null +++ b/src/test/ui/existential_types/existential_type-pass.rs @@ -0,0 +1,89 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![feature(existential_type)] + +fn main() { + assert_eq!(foo().to_string(), "foo"); + assert_eq!(bar1().to_string(), "bar1"); + assert_eq!(bar2().to_string(), "bar2"); + let mut x = bar1(); + x = bar2(); + assert_eq!(boo::boo().to_string(), "boo"); + assert_eq!(my_iter(42u8).collect::>(), vec![42u8]); +} + +// single definition +existential type Foo: std::fmt::Display; + +fn foo() -> Foo { + "foo" +} + +// two definitions +existential type Bar: std::fmt::Display; + +fn bar1() -> Bar { + "bar1" +} + +fn bar2() -> Bar { + "bar2" +} + +// definition in submodule +existential type Boo: std::fmt::Display; + +mod boo { + pub fn boo() -> super::Boo { + "boo" + } +} + +existential type MyIter: Iterator; + +fn my_iter(t: T) -> MyIter { + std::iter::once(t) +} + +fn my_iter2(t: T) -> MyIter { + std::iter::once(t) +} + +// param names should not have an effect! +fn my_iter3(u: U) -> MyIter { + std::iter::once(u) +} + +// param position should not have an effect! +fn my_iter4(_: U, v: V) -> MyIter { + std::iter::once(v) +} + +// param names should not have an effect! +existential type MyOtherIter: Iterator; + +fn my_other_iter(u: U) -> MyOtherIter { + std::iter::once(u) +} + +trait Trait {} +existential type GenericBound<'a, T: Trait>: Sized + 'a; + +fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> { + t +} + +mod pass_through { + pub existential type Passthrough: Sized + 'static; + + fn define_passthrough(t: T) -> Passthrough { + t + } +} + +fn use_passthrough(x: pass_through::Passthrough) -> pass_through::Passthrough { + x +} -- cgit 1.4.1-3-g733a5 From b779f45fedef4b02bd0daebba34b39d5d367181c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 29 Jul 2019 04:07:33 +0200 Subject: Add test for #53678. --- .../issue-53678-generator-and-const-fn.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs (limited to 'src/test') diff --git a/src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs b/src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs new file mode 100644 index 00000000000..d964f2b74ff --- /dev/null +++ b/src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(const_fn, generators, generator_trait, existential_type)] + +use std::ops::Generator; + +existential type GenOnce: Generator; + +const fn const_generator(yielding: Y, returning: R) -> GenOnce { + move || { + yield yielding; + + return returning; + } +} + +const FOO: GenOnce = const_generator(10, 100); + +fn main() {} -- cgit 1.4.1-3-g733a5 From 1e927d8689bc605cb1b1ff5b7bf9c062f6885443 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 29 Jul 2019 04:07:51 +0200 Subject: Add test for #60407. --- src/test/ui/existential_types/issue-60407.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/ui/existential_types/issue-60407.rs (limited to 'src/test') diff --git a/src/test/ui/existential_types/issue-60407.rs b/src/test/ui/existential_types/issue-60407.rs new file mode 100644 index 00000000000..52162c491b5 --- /dev/null +++ b/src/test/ui/existential_types/issue-60407.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(existential_type)] + +existential type Debuggable: core::fmt::Debug; + +static mut TEST: Option = None; + +fn main() { + unsafe { TEST = Some(foo()) } +} + +fn foo() -> Debuggable { + 0u32 +} -- cgit 1.4.1-3-g733a5 From a54dd2318ae42fa4c6602cd37d07e837464df082 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 29 Jul 2019 04:08:04 +0200 Subject: Add test for #60564. --- src/test/ui/existential_types/issue-60564.rs | 26 ++++++++++++++++++++++++ src/test/ui/existential_types/issue-60564.stderr | 25 +++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/test/ui/existential_types/issue-60564.rs create mode 100644 src/test/ui/existential_types/issue-60564.stderr (limited to 'src/test') diff --git a/src/test/ui/existential_types/issue-60564.rs b/src/test/ui/existential_types/issue-60564.rs new file mode 100644 index 00000000000..cb3914ddd1d --- /dev/null +++ b/src/test/ui/existential_types/issue-60564.rs @@ -0,0 +1,26 @@ +#![feature(existential_type)] + +trait IterBits { + type BitsIter: Iterator; + fn iter_bits(self, n: u8) -> Self::BitsIter; +} + +existential type IterBitsIter: std::iter::Iterator; +//~^ ERROR could not find defining uses + +impl IterBits for T +where + T: std::ops::Shr + + std::ops::BitAnd + + std::convert::From + + std::convert::TryInto, + E: std::fmt::Debug, +{ + type BitsIter = IterBitsIter; + fn iter_bits(self, n: u8) -> Self::BitsIter { + //~^ ERROR type parameter `E` is part of concrete type but not used + (0u8..n) + .rev() + .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + } +} diff --git a/src/test/ui/existential_types/issue-60564.stderr b/src/test/ui/existential_types/issue-60564.stderr new file mode 100644 index 00000000000..d8480b52157 --- /dev/null +++ b/src/test/ui/existential_types/issue-60564.stderr @@ -0,0 +1,25 @@ +error[E0601]: `main` function not found in crate `issue_60564` + | + = note: consider adding a `main` function to `$DIR/issue-60564.rs` + +error: type parameter `E` is part of concrete type but not used in parameter list for existential type + --> $DIR/issue-60564.rs:20:49 + | +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: could not find defining uses + --> $DIR/issue-60564.rs:8:1 + | +LL | existential type IterBitsIter: std::iter::Iterator; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0601`. -- cgit 1.4.1-3-g733a5 From 870efe34c8c86a3aef4db628b429425a216b41bd Mon Sep 17 00:00:00 2001 From: CrLF0710 Date: Mon, 29 Jul 2019 01:05:31 +0800 Subject: Add very simple edition check to tidy; and add missing edition = 2018s. --- .../run-make/thumb-none-qemu/example/Cargo.toml | 2 +- .../run-make/thumb-none-qemu/example/src/main.rs | 16 ++++---- src/tools/rustc-std-workspace-alloc/Cargo.toml | 1 + src/tools/tidy/src/edition.rs | 45 ++++++++++++++++++++++ src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/main.rs | 1 + 6 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 src/tools/tidy/src/edition.rs (limited to 'src/test') diff --git a/src/test/run-make/thumb-none-qemu/example/Cargo.toml b/src/test/run-make/thumb-none-qemu/example/Cargo.toml index 499553304c6..73fdee71f0c 100644 --- a/src/test/run-make/thumb-none-qemu/example/Cargo.toml +++ b/src/test/run-make/thumb-none-qemu/example/Cargo.toml @@ -2,7 +2,7 @@ name = "example" version = "0.1.0" authors = ["Hideki Sekine "] -# edition = "2018" +edition = "2018" [dependencies] cortex-m = "0.5.4" diff --git a/src/test/run-make/thumb-none-qemu/example/src/main.rs b/src/test/run-make/thumb-none-qemu/example/src/main.rs index d88a327ef08..4a08419a07e 100644 --- a/src/test/run-make/thumb-none-qemu/example/src/main.rs +++ b/src/test/run-make/thumb-none-qemu/example/src/main.rs @@ -1,16 +1,14 @@ // #![feature(stdsimd)] #![no_main] #![no_std] - -extern crate cortex_m; - -extern crate cortex_m_rt as rt; -extern crate cortex_m_semihosting as semihosting; -extern crate panic_halt; - use core::fmt::Write; use cortex_m::asm; -use rt::entry; +use cortex_m_rt::entry; +use cortex_m_semihosting as semihosting; + +//FIXME: This imports the provided #[panic_handler]. +#[allow(rust_2018_idioms)] +extern crate panic_halt; entry!(main); @@ -22,7 +20,7 @@ fn main() -> ! { // write something through semihosting interface let mut hstdout = semihosting::hio::hstdout().unwrap(); - write!(hstdout, "x = {}\n", x); + let _ = write!(hstdout, "x = {}\n", x); // exit from qemu semihosting::debug::exit(semihosting::debug::EXIT_SUCCESS); diff --git a/src/tools/rustc-std-workspace-alloc/Cargo.toml b/src/tools/rustc-std-workspace-alloc/Cargo.toml index 05df1fddc7f..ef7dc812af9 100644 --- a/src/tools/rustc-std-workspace-alloc/Cargo.toml +++ b/src/tools/rustc-std-workspace-alloc/Cargo.toml @@ -6,6 +6,7 @@ license = 'MIT OR Apache-2.0' description = """ Hack for the compiler's own build system """ +edition = "2018" [lib] path = "lib.rs" diff --git a/src/tools/tidy/src/edition.rs b/src/tools/tidy/src/edition.rs new file mode 100644 index 00000000000..4a2e49fd1c3 --- /dev/null +++ b/src/tools/tidy/src/edition.rs @@ -0,0 +1,45 @@ +//! Tidy check to ensure that crate `edition` is '2018' +//! + +use std::path::Path; + +fn filter_dirs(path: &Path) -> bool { + // FIXME: just use super::filter_dirs after the submodules are updated. + if super::filter_dirs(path) { + return true; + } + let skip = [ + "src/doc/book/second-edition", + "src/doc/book/2018-edition", + "src/doc/book/ci/stable-check", + "src/doc/reference/stable-check", + ]; + skip.iter().any(|p| path.ends_with(p)) +} + +fn is_edition_2018(mut line: &str) -> bool { + line = line.trim(); + line == "edition = \"2018\"" || line == "edition = \'2018\'" +} + +pub fn check(path: &Path, bad: &mut bool) { + super::walk( + path, + &mut |path| filter_dirs(path) || path.ends_with("src/test"), + &mut |entry, contents| { + let file = entry.path(); + let filename = file.file_name().unwrap(); + if filename != "Cargo.toml" { + return; + } + let has_edition = contents.lines().any(is_edition_2018); + if !has_edition { + tidy_error!( + bad, + "{} doesn't have `edition = \"2018\"` on a separate line", + file.display() + ); + } + }, + ); +} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index eca8001a9d2..e01184e3658 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -34,6 +34,7 @@ pub mod style; pub mod errors; pub mod features; pub mod cargo; +pub mod edition; pub mod pal; pub mod deps; pub mod extdeps; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 3acb50547da..5deac52f08b 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -22,6 +22,7 @@ fn main() { style::check(&path, &mut bad); errors::check(&path, &mut bad); cargo::check(&path, &mut bad); + edition::check(&path, &mut bad); let collected = features::check(&path, &mut bad, verbose); pal::check(&path, &mut bad); unstable_book::check(&path, collected, &mut bad); -- cgit 1.4.1-3-g733a5 From 15bc63e8bfd575c709a45f7c6845acfe0f3fdc92 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 29 Jul 2019 09:03:27 +0200 Subject: Add syntactic test for rest patterns. --- src/test/ui/pattern/rest-pat-syntactic.rs | 70 +++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/test/ui/pattern/rest-pat-syntactic.rs (limited to 'src/test') diff --git a/src/test/ui/pattern/rest-pat-syntactic.rs b/src/test/ui/pattern/rest-pat-syntactic.rs new file mode 100644 index 00000000000..9656a0b5de9 --- /dev/null +++ b/src/test/ui/pattern/rest-pat-syntactic.rs @@ -0,0 +1,70 @@ +// Here we test that `..` is allowed in all pattern locations *syntactically*. +// The semantic test is in `rest-pat-semantic-disallowed.rs`. + +// check-pass + +fn main() {} + +macro_rules! accept_pat { + ($p:pat) => {} +} + +accept_pat!(..); + +#[cfg(FALSE)] +fn rest_patterns() { + // Top level: + fn foo(..: u8) {} + let ..; + + // Box patterns: + let box ..; + + // In or-patterns: + match x { + .. | .. => {} + } + + // Ref patterns: + let &..; + let &mut ..; + + // Ident patterns: + let x @ ..; + let ref x @ ..; + let ref mut x @ ..; + + // Tuple: + let (..); // This is interpreted as a tuple pattern, not a parenthesis one. + let (..,); // Allowing trailing comma. + let (.., .., ..); // Duplicates also. + let (.., P, ..); // Including with things in between. + + // Tuple struct (same idea as for tuple patterns): + let A(..); + let A(..,); + let A(.., .., ..); + let A(.., P, ..); + + // Array/Slice (like with tuple patterns): + let [..]; + let [..,]; + let [.., .., ..]; + let [.., P, ..]; + + // Random walk to guard against special casing: + match x { + .. | + [ + ( + box .., + &(..), + &mut .., + x @ .. + ), + ref x @ .., + ] | + ref mut x @ .. + => {} + } +} -- cgit 1.4.1-3-g733a5 From 0fb9295e1231d0878ec3cd06811e3e0dc8c7ce4f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 29 Jul 2019 20:04:07 +0100 Subject: Add another test for const parameter (non) hygiene. --- .../ui/hygiene/issue-61574-const-parameters.rs | 32 ++++++++++++++++++++++ .../ui/hygiene/issue-61574-const-parameters.stderr | 6 ++++ 2 files changed, 38 insertions(+) create mode 100644 src/test/ui/hygiene/issue-61574-const-parameters.rs create mode 100644 src/test/ui/hygiene/issue-61574-const-parameters.stderr (limited to 'src/test') diff --git a/src/test/ui/hygiene/issue-61574-const-parameters.rs b/src/test/ui/hygiene/issue-61574-const-parameters.rs new file mode 100644 index 00000000000..dcfb42287d5 --- /dev/null +++ b/src/test/ui/hygiene/issue-61574-const-parameters.rs @@ -0,0 +1,32 @@ +// A more comprehensive test that const parameters have correctly implemented +// hygiene + +// check-pass + +#![feature(const_generics)] + +use std::ops::Add; + +struct VectorLike([T; {SIZE}]); + +macro_rules! impl_operator_overload { + ($trait_ident:ident, $method_ident:ident) => { + + impl $trait_ident for VectorLike + where + T: $trait_ident, + { + type Output = VectorLike; + + fn $method_ident(self, _: VectorLike) -> VectorLike { + let _ = SIZE; + unimplemented!() + } + } + + } +} + +impl_operator_overload!(Add, add); + +fn main() {} diff --git a/src/test/ui/hygiene/issue-61574-const-parameters.stderr b/src/test/ui/hygiene/issue-61574-const-parameters.stderr new file mode 100644 index 00000000000..302b5fde887 --- /dev/null +++ b/src/test/ui/hygiene/issue-61574-const-parameters.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-61574-const-parameters.rs:6:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 6c7613b7fd8e2ce739b562a650aad25b32896574 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 29 Jul 2019 21:04:32 +0200 Subject: Add semantic test for rest patterns. --- .../ui/pattern/rest-pat-semantic-disallowed.rs | 82 +++++++++ .../ui/pattern/rest-pat-semantic-disallowed.stderr | 188 +++++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 src/test/ui/pattern/rest-pat-semantic-disallowed.rs create mode 100644 src/test/ui/pattern/rest-pat-semantic-disallowed.stderr (limited to 'src/test') diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.rs b/src/test/ui/pattern/rest-pat-semantic-disallowed.rs new file mode 100644 index 00000000000..36a45a3ccdc --- /dev/null +++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.rs @@ -0,0 +1,82 @@ +// Here we test that rest patterns, i.e. `..`, are not allowed +// outside of slice (+ ident patterns witin those), tuple, +// and tuple struct patterns and that duplicates are caught in these contexts. + +#![feature(slice_patterns, box_patterns)] + +fn main() {} + +macro_rules! mk_pat { + () => { .. } //~ ERROR `..` patterns are not allowed here +} + +fn rest_patterns() { + let mk_pat!(); + + // Top level: + fn foo(..: u8) {} //~ ERROR `..` patterns are not allowed here + let ..; //~ ERROR `..` patterns are not allowed here + + // Box patterns: + let box ..; //~ ERROR `..` patterns are not allowed here + + // In or-patterns: + match 1 { + 1 | .. => {} //~ ERROR `..` patterns are not allowed here + } + + // Ref patterns: + let &..; //~ ERROR `..` patterns are not allowed here + let &mut ..; //~ ERROR `..` patterns are not allowed here + + // Ident patterns: + let x @ ..; //~ ERROR `..` patterns are not allowed here + let ref x @ ..; //~ ERROR `..` patterns are not allowed here + let ref mut x @ ..; //~ ERROR `..` patterns are not allowed here + + // Tuple: + let (..): (u8,); // OK. + let (..,): (u8,); // OK. + let ( + .., + .., //~ ERROR `..` can only be used once per tuple pattern + .. //~ ERROR `..` can only be used once per tuple pattern + ): (u8, u8, u8); + let ( + .., + x, + .. //~ ERROR `..` can only be used once per tuple pattern + ): (u8, u8, u8); + + struct A(u8, u8, u8); + + // Tuple struct (same idea as for tuple patterns): + let A(..); // OK. + let A(..,); // OK. + let A( + .., + .., //~ ERROR `..` can only be used once per tuple struct pattern + .. //~ ERROR `..` can only be used once per tuple struct pattern + ); + let A( + .., + x, + .. //~ ERROR `..` can only be used once per tuple struct pattern + ); + + // Array/Slice: + let [..]: &[u8]; // OK. + let [..,]: &[u8]; // OK. + let [ + .., + .., //~ ERROR `..` can only be used once per slice pattern + .. //~ ERROR `..` can only be used once per slice pattern + ]: &[u8]; + let [ + .., + ref x @ .., //~ ERROR `..` can only be used once per slice pattern + ref mut y @ .., //~ ERROR `..` can only be used once per slice pattern + (ref z @ ..), //~ ERROR `..` patterns are not allowed here + .. //~ ERROR `..` can only be used once per slice pattern + ]: &[u8]; +} diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr new file mode 100644 index 00000000000..826f76b356c --- /dev/null +++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr @@ -0,0 +1,188 @@ +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:10:13 + | +LL | () => { .. } + | ^^ +... +LL | let mk_pat!(); + | --------- in this macro invocation + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:18:9 + | +LL | let ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:21:13 + | +LL | let box ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:25:13 + | +LL | 1 | .. => {} + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:29:10 + | +LL | let &..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:30:14 + | +LL | let &mut ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:33:13 + | +LL | let x @ ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:34:17 + | +LL | let ref x @ ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:35:21 + | +LL | let ref mut x @ ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` can only be used once per tuple pattern + --> $DIR/rest-pat-semantic-disallowed.rs:42:9 + | +LL | .., + | -- previously used here +LL | .., + | ^^ can only be used once per tuple pattern + +error: `..` can only be used once per tuple pattern + --> $DIR/rest-pat-semantic-disallowed.rs:43:9 + | +LL | .., + | -- previously used here +LL | .., +LL | .. + | ^^ can only be used once per tuple pattern + +error: `..` can only be used once per tuple pattern + --> $DIR/rest-pat-semantic-disallowed.rs:48:9 + | +LL | .., + | -- previously used here +LL | x, +LL | .. + | ^^ can only be used once per tuple pattern + +error: `..` can only be used once per tuple struct pattern + --> $DIR/rest-pat-semantic-disallowed.rs:58:9 + | +LL | .., + | -- previously used here +LL | .., + | ^^ can only be used once per tuple struct pattern + +error: `..` can only be used once per tuple struct pattern + --> $DIR/rest-pat-semantic-disallowed.rs:59:9 + | +LL | .., + | -- previously used here +LL | .., +LL | .. + | ^^ can only be used once per tuple struct pattern + +error: `..` can only be used once per tuple struct pattern + --> $DIR/rest-pat-semantic-disallowed.rs:64:9 + | +LL | .., + | -- previously used here +LL | x, +LL | .. + | ^^ can only be used once per tuple struct pattern + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:72:9 + | +LL | .., + | -- previously used here +LL | .., + | ^^ can only be used once per slice pattern + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:73:9 + | +LL | .., + | -- previously used here +LL | .., +LL | .. + | ^^ can only be used once per slice pattern + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:77:17 + | +LL | .., + | -- previously used here +LL | ref x @ .., + | ^^ can only be used once per slice pattern + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:78:21 + | +LL | .., + | -- previously used here +LL | ref x @ .., +LL | ref mut y @ .., + | ^^ can only be used once per slice pattern + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:79:18 + | +LL | (ref z @ ..), + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:80:9 + | +LL | .., + | -- previously used here +... +LL | .. + | ^^ can only be used once per slice pattern + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:17:12 + | +LL | fn foo(..: u8) {} + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: aborting due to 22 previous errors + -- cgit 1.4.1-3-g733a5