From d419a5fdaebb36dbf3c600f624c964d9ea651661 Mon Sep 17 00:00:00 2001 From: Janusz Marcinkiewicz Date: Sun, 1 Dec 2019 13:39:01 +0100 Subject: [PATCH 01/38] Fix pointing at arg when cause is outside of call --- src/librustc_typeck/check/mod.rs | 65 +++++++++++++++------------ src/test/ui/issues/issue-66923.rs | 13 ++++++ src/test/ui/issues/issue-66923.stderr | 19 ++++++++ 3 files changed, 69 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/issues/issue-66923.rs create mode 100644 src/test/ui/issues/issue-66923.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c7a0190a1d1b4..5e644df99beeb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3880,36 +3880,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_sp: Span, args: &'tcx [hir::Expr], ) { - if !call_sp.desugaring_kind().is_some() { - // We *do not* do this for desugared call spans to keep good diagnostics when involving - // the `?` operator. - for error in errors { - if let ty::Predicate::Trait(predicate) = error.obligation.predicate { - // Collect the argument position for all arguments that could have caused this - // `FulfillmentError`. - let mut referenced_in = final_arg_types.iter() - .map(|(i, checked_ty, _)| (i, checked_ty)) - .chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty))) - .flat_map(|(i, ty)| { - let ty = self.resolve_vars_if_possible(ty); - // We walk the argument type because the argument's type could have - // been `Option`, but the `FulfillmentError` references `T`. - ty.walk() - .filter(|&ty| ty == predicate.skip_binder().self_ty()) - .map(move |_| *i) - }) - .collect::>(); + // We *do not* do this for desugared call spans to keep good diagnostics when involving + // the `?` operator. + if call_sp.desugaring_kind().is_some() { + return + } + + for error in errors { + // Only if the cause is somewhere inside the expression we want try to point at arg. + // Otherwise, it means that the cause is somewhere else and we should not change + // anything because we can break the correct span. + if !call_sp.contains(error.obligation.cause.span) { + continue + } + + if let ty::Predicate::Trait(predicate) = error.obligation.predicate { + // Collect the argument position for all arguments that could have caused this + // `FulfillmentError`. + let mut referenced_in = final_arg_types.iter() + .map(|(i, checked_ty, _)| (i, checked_ty)) + .chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty))) + .flat_map(|(i, ty)| { + let ty = self.resolve_vars_if_possible(ty); + // We walk the argument type because the argument's type could have + // been `Option`, but the `FulfillmentError` references `T`. + ty.walk() + .filter(|&ty| ty == predicate.skip_binder().self_ty()) + .map(move |_| *i) + }) + .collect::>(); - // Both checked and coerced types could have matched, thus we need to remove - // duplicates. - referenced_in.dedup(); + // Both checked and coerced types could have matched, thus we need to remove + // duplicates. + referenced_in.dedup(); - if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { - // We make sure that only *one* argument matches the obligation failure - // and we assign the obligation's span to its expression's. - error.obligation.cause.span = args[ref_in].span; - error.points_at_arg_span = true; - } + if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { + // We make sure that only *one* argument matches the obligation failure + // and we assign the obligation's span to its expression's. + error.obligation.cause.span = args[ref_in].span; + error.points_at_arg_span = true; } } } diff --git a/src/test/ui/issues/issue-66923.rs b/src/test/ui/issues/issue-66923.rs new file mode 100644 index 0000000000000..a452e6384a3d4 --- /dev/null +++ b/src/test/ui/issues/issue-66923.rs @@ -0,0 +1,13 @@ +fn main() { + let v = vec![1_f64, 2.2_f64]; + let mut fft: Vec> = vec![]; + + let x1: &[f64] = &v; + let x2: Vec = x1.into_iter().collect(); + //~^ ERROR a collection of type + fft.push(x2); + + let x3 = x1.into_iter().collect::>(); + //~^ ERROR a collection of type + fft.push(x3); +} diff --git a/src/test/ui/issues/issue-66923.stderr b/src/test/ui/issues/issue-66923.stderr new file mode 100644 index 0000000000000..a2eec7caee507 --- /dev/null +++ b/src/test/ui/issues/issue-66923.stderr @@ -0,0 +1,19 @@ +error[E0277]: a collection of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923.rs:6:39 + | +LL | let x2: Vec = x1.into_iter().collect(); + | ^^^^^^^ a collection of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error[E0277]: a collection of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923.rs:10:29 + | +LL | let x3 = x1.into_iter().collect::>(); + | ^^^^^^^ a collection of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From e305bf8bc8cecaf93080f07962a4f763cd66f5ce Mon Sep 17 00:00:00 2001 From: Janusz Marcinkiewicz Date: Tue, 3 Dec 2019 08:20:17 +0100 Subject: [PATCH 02/38] Rename tests and add short test description --- .../core-traits-no-impls-length-33.rs | 1 + .../core-traits-no-impls-length-33.stderr | 19 ++++++++++++++----- ...ssue-66923-show-error-for-correct-call.rs} | 6 ++++-- ...e-66923-show-error-for-correct-call.stderr | 19 +++++++++++++++++++ src/test/ui/issues/issue-66923.stderr | 19 ------------------- 5 files changed, 38 insertions(+), 26 deletions(-) rename src/test/ui/issues/{issue-66923.rs => issue-66923-show-error-for-correct-call.rs} (61%) create mode 100644 src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr delete mode 100644 src/test/ui/issues/issue-66923.stderr diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs index 8397d204f35cf..7fa059583f539 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs @@ -6,6 +6,7 @@ pub fn no_debug() { pub fn no_hash() { use std::collections::HashSet; let mut set = HashSet::new(); + //~^ ERROR arrays only have std trait implementations for lengths 0..=32 set.insert([0_usize; 33]); //~^ ERROR arrays only have std trait implementations for lengths 0..=32 } diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr index 594a0d4b5d844..d885c98dcb287 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr @@ -8,15 +8,24 @@ LL | println!("{:?}", [0_usize; 33]); = note: required by `std::fmt::Debug::fmt` error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/core-traits-no-impls-length-33.rs:9:16 + --> $DIR/core-traits-no-impls-length-33.rs:10:16 | LL | set.insert([0_usize; 33]); | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]` | = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]` +error[E0277]: arrays only have std trait implementations for lengths 0..=32 + --> $DIR/core-traits-no-impls-length-33.rs:8:19 + | +LL | let mut set = HashSet::new(); + | ^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]` + | + = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]` + = note: required by `std::collections::HashSet::::new` + error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]` - --> $DIR/core-traits-no-impls-length-33.rs:14:19 + --> $DIR/core-traits-no-impls-length-33.rs:15:19 | LL | [0_usize; 33] == [1_usize; 33] | ------------- ^^ ------------- [usize; 33] @@ -26,7 +35,7 @@ LL | [0_usize; 33] == [1_usize; 33] = note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]` error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]` - --> $DIR/core-traits-no-impls-length-33.rs:19:19 + --> $DIR/core-traits-no-impls-length-33.rs:20:19 | LL | [0_usize; 33] < [1_usize; 33] | ------------- ^ ------------- [usize; 33] @@ -36,7 +45,7 @@ LL | [0_usize; 33] < [1_usize; 33] = note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]` error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied - --> $DIR/core-traits-no-impls-length-33.rs:24:14 + --> $DIR/core-traits-no-impls-length-33.rs:25:14 | LL | for _ in &[0_usize; 33] { | ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]` @@ -48,7 +57,7 @@ LL | for _ in &[0_usize; 33] { <&'a mut [T] as std::iter::IntoIterator> = note: required by `std::iter::IntoIterator::into_iter` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0277, E0369. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-66923.rs b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs similarity index 61% rename from src/test/ui/issues/issue-66923.rs rename to src/test/ui/issues/issue-66923-show-error-for-correct-call.rs index a452e6384a3d4..8332807397247 100644 --- a/src/test/ui/issues/issue-66923.rs +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs @@ -1,13 +1,15 @@ +// This test checks that errors are showed for lines with `collect` rather than `push` method. + fn main() { let v = vec![1_f64, 2.2_f64]; let mut fft: Vec> = vec![]; let x1: &[f64] = &v; let x2: Vec = x1.into_iter().collect(); - //~^ ERROR a collection of type + //~^ ERROR a value of type fft.push(x2); let x3 = x1.into_iter().collect::>(); - //~^ ERROR a collection of type + //~^ ERROR a value of type fft.push(x3); } diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr new file mode 100644 index 0000000000000..8e7ee97e0b907 --- /dev/null +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -0,0 +1,19 @@ +error[E0277]: a value of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39 + | +LL | let x2: Vec = x1.into_iter().collect(); + | ^^^^^^^ value of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error[E0277]: a value of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29 + | +LL | let x3 = x1.into_iter().collect::>(); + | ^^^^^^^ value of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-66923.stderr b/src/test/ui/issues/issue-66923.stderr deleted file mode 100644 index a2eec7caee507..0000000000000 --- a/src/test/ui/issues/issue-66923.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: a collection of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` - --> $DIR/issue-66923.rs:6:39 - | -LL | let x2: Vec = x1.into_iter().collect(); - | ^^^^^^^ a collection of type `std::vec::Vec` cannot be built from `std::iter::Iterator` - | - = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` - -error[E0277]: a collection of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` - --> $DIR/issue-66923.rs:10:29 - | -LL | let x3 = x1.into_iter().collect::>(); - | ^^^^^^^ a collection of type `std::vec::Vec` cannot be built from `std::iter::Iterator` - | - = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. From c4bbe9cbbe9921646cdedb856e34dc951641ed96 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 30 Nov 2019 18:25:44 +0100 Subject: [PATCH 03/38] Alias `TraitItem` & `ImplItem`. Allow defaultness on trait items syntactically. --- src/librustc_parse/parser/item.rs | 6 ++- src/librustc_passes/ast_validation.rs | 9 +++++ src/libsyntax/ast.rs | 22 +++-------- src/libsyntax/mut_visit.rs | 3 +- src/libsyntax/print/pprust.rs | 1 + src/libsyntax_expand/placeholders.rs | 1 + src/test/ui/issues/issue-60075.stderr | 2 +- src/test/ui/parser/issue-32446.stderr | 4 +- .../parser/macro/trait-non-item-macros.stderr | 4 +- .../missing-close-brace-in-trait.stderr | 4 +- ...ait-item-with-defaultness-fail-semantic.rs | 10 +++++ ...item-with-defaultness-fail-semantic.stderr | 38 +++++++++++++++++++ .../trait-item-with-defaultness-pass.rs | 13 +++++++ 13 files changed, 90 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs create mode 100644 src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr create mode 100644 src/test/ui/parser/trait-item-with-defaultness-pass.rs diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 34ef12e818c57..c159fb66d5070 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -714,9 +714,9 @@ impl<'a> Parser<'a> { id: DUMMY_NODE_ID, span: lo.to(self.prev_span), ident: name, + attrs, vis, defaultness, - attrs, generics, kind, tokens: None, @@ -882,6 +882,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, TraitItem> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; + let defaultness = self.parse_defaultness(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { @@ -895,12 +896,13 @@ impl<'a> Parser<'a> { Ok(TraitItem { id: DUMMY_NODE_ID, + span: lo.to(self.prev_span), ident: name, attrs, vis, + defaultness, generics, kind, - span: lo.to(self.prev_span), tokens: None, }) } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 202b6ae2f94c4..a078a36db7ac4 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -271,6 +271,14 @@ impl<'a> AstValidator<'a> { forbid, and warn are the only allowed built-in attributes in function parameters") }); } + + fn check_defaultness(&self, span: Span, defaultness: Defaultness) { + if let Defaultness::Default = defaultness { + self.err_handler() + .struct_span_err(span, "`default` is only allowed on items in `impl` definitions") + .emit(); + } + } } enum GenericPosition { @@ -746,6 +754,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_trait_item(&mut self, ti: &'a TraitItem) { self.invalid_visibility(&ti.vis, None); + self.check_defaultness(ti.span, ti.defaultness); visit::walk_trait_item(self, ti); } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 92ba071a03d68..964acfa92b9bb 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1603,24 +1603,12 @@ pub struct FnSig { pub decl: P, } -/// Represents an item declaration within a trait declaration, +pub type TraitItem = ImplItem; + +/// Represents the kind of an item declaration within a trait declaration, /// possibly including a default implementation. A trait item is /// either required (meaning it doesn't have an implementation, just a /// signature) or provided (meaning it has a default implementation). -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct TraitItem { - pub attrs: Vec, - pub id: NodeId, - pub span: Span, - pub vis: Visibility, - pub ident: Ident, - - pub generics: Generics, - pub kind: TraitItemKind, - /// See `Item::tokens` for what this is. - pub tokens: Option, -} - #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum TraitItemKind { Const(P, Option>), @@ -1631,7 +1619,7 @@ pub enum TraitItemKind { /// Represents anything within an `impl` block. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct ImplItem { +pub struct ImplItem { pub attrs: Vec, pub id: NodeId, pub span: Span, @@ -1640,7 +1628,7 @@ pub struct ImplItem { pub defaultness: Defaultness, pub generics: Generics, - pub kind: ImplItemKind, + pub kind: K, /// See `Item::tokens` for what this is. pub tokens: Option, } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index f8795d885d216..9d0a29f29511d 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -939,7 +939,8 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { pub fn noop_flat_map_trait_item(mut item: TraitItem, visitor: &mut T) -> SmallVec<[TraitItem; 1]> { - let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item; + let TraitItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } = + &mut item; visitor.visit_id(id); visitor.visit_ident(ident); visitor.visit_vis(vis); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f0c5fb32fb16d..2e3ea5e24440f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1550,6 +1550,7 @@ impl<'a> State<'a> { self.hardbreak_if_not_bol(); self.maybe_print_comment(ti.span.lo()); self.print_outer_attributes(&ti.attrs); + self.print_defaultness(ti.defaultness); match ti.kind { ast::TraitItemKind::Const(ref ty, ref default) => { self.print_associated_const( diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs index faea04e691be5..6057be9826a51 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -53,6 +53,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option AstFragment::TraitItems(smallvec![ast::TraitItem { id, span, ident, vis, attrs, generics, kind: ast::TraitItemKind::Macro(mac_placeholder()), + defaultness: ast::Defaultness::Final, tokens: None, }]), AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem { diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index e0b15130c337d..e8ef981f515fc 100644 --- a/src/test/ui/issues/issue-60075.stderr +++ b/src/test/ui/issues/issue-60075.stderr @@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}` LL | }); | ^ expected one of `.`, `;`, `?`, `else`, or an operator -error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;` --> $DIR/issue-60075.rs:6:11 | LL | fn qux() -> Option { diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr index 70256a59231fb..1a97f54160b24 100644 --- a/src/test/ui/parser/issue-32446.stderr +++ b/src/test/ui/parser/issue-32446.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...` --> $DIR/issue-32446.rs:4:11 | LL | trait T { ... } - | ^^^ expected one of 9 possible tokens + | ^^^ expected one of 10 possible tokens error: aborting due to previous error diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr index 0a433ab278e43..7647ba500e03a 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.stderr +++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2` --> $DIR/trait-non-item-macros.rs:2:19 | LL | ($a:expr) => ($a) - | ^^ expected one of 8 possible tokens + | ^^ expected one of 9 possible tokens ... LL | bah!(2); | -------- in this macro invocation diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index cbaf9315e8540..7e8abf22d55ab 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,11 +7,11 @@ LL | trait T { LL | fn main() {} | ^ -error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct` +error: expected one of `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct` --> $DIR/missing-close-brace-in-trait.rs:5:12 | LL | pub(crate) struct Bar(); - | ^^^^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe` + | ^^^^^^ expected one of 7 possible tokens error[E0601]: `main` function not found in crate `missing_close_brace_in_trait` --> $DIR/missing-close-brace-in-trait.rs:1:1 diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs new file mode 100644 index 0000000000000..b67e30637aa62 --- /dev/null +++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs @@ -0,0 +1,10 @@ +fn main() {} + +trait X { + default const A: u8; //~ ERROR `default` is only allowed on items in `impl` definitions + default const B: u8 = 0; //~ ERROR `default` is only allowed on items in `impl` definitions + default type D; //~ ERROR `default` is only allowed on items in `impl` definitions + default type C: Ord; //~ ERROR `default` is only allowed on items in `impl` definitions + default fn f1(); //~ ERROR `default` is only allowed on items in `impl` definitions + default fn f2() {} //~ ERROR `default` is only allowed on items in `impl` definitions +} diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr new file mode 100644 index 0000000000000..48b502a1506b1 --- /dev/null +++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr @@ -0,0 +1,38 @@ +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:4:5 + | +LL | default const A: u8; + | ^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:5:5 + | +LL | default const B: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5 + | +LL | default type D; + | ^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5 + | +LL | default type C: Ord; + | ^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5 + | +LL | default fn f1(); + | ^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5 + | +LL | default fn f2() {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/trait-item-with-defaultness-pass.rs b/src/test/ui/parser/trait-item-with-defaultness-pass.rs new file mode 100644 index 0000000000000..a6318bd99e2f6 --- /dev/null +++ b/src/test/ui/parser/trait-item-with-defaultness-pass.rs @@ -0,0 +1,13 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +trait X { + default const A: u8; + default const B: u8 = 0; + default type D; + default type C: Ord; + default fn f1(); + default fn f2() {} +} From 73557faed23678fc443f3fa52727b5f200f597d2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 04:12:28 +0100 Subject: [PATCH 04/38] Use `Option` in `ImplItemKind::Const`. --- src/librustc/hir/lowering/item.rs | 8 +++++- src/librustc_parse/parser/item.rs | 17 +++++++----- src/librustc_passes/ast_validation.rs | 26 ++++++++++++++----- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/libsyntax/ast.rs | 4 +-- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 2 +- src/test/ui/parser/impl-item-const-pass.rs | 8 ++++++ .../parser/impl-item-const-semantic-fail.rs | 7 +++++ .../impl-item-const-semantic-fail.stderr | 8 ++++++ 11 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/parser/impl-item-const-pass.rs create mode 100644 src/test/ui/parser/impl-item-const-semantic-fail.rs create mode 100644 src/test/ui/parser/impl-item-const-semantic-fail.stderr diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index ff9d8c85df8b9..32b36d2021b0f 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -899,7 +899,13 @@ impl LoweringContext<'_> { self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::ImplItemKind::Const( self.lower_ty(ty, ImplTraitContext::disallowed()), - self.lower_const_body(expr), + match expr { + Some(expr) => self.lower_const_body(expr), + None => self.lower_body(|this| ( + hir_vec![], + this.expr(i.span, hir::ExprKind::Err, ThinVec::new()), + )), + } ), ), ImplItemKind::Method(ref sig, ref body) => { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index c159fb66d5070..68fdfd24d6164 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -756,13 +756,16 @@ impl<'a> Parser<'a> { /// ImplItemConst = "const" Ident ":" Ty "=" Expr ";" fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { self.expect_keyword(kw::Const)?; - let name = self.parse_ident()?; + let ident = self.parse_ident()?; self.expect(&token::Colon)?; - let typ = self.parse_ty()?; - self.expect(&token::Eq)?; - let expr = self.parse_expr()?; + let ty = self.parse_ty()?; + let expr = if self.eat(&token::Eq) { + Some(self.parse_expr()?) + } else { + None + }; self.expect_semi()?; - Ok((name, ImplItemKind::Const(typ, expr), Generics::default())) + Ok((ident, ImplItemKind::Const(ty, expr), Generics::default())) } /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. @@ -912,13 +915,13 @@ impl<'a> Parser<'a> { let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; - let default = if self.eat(&token::Eq) { + let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; - Ok((ident, TraitItemKind::Const(ty, default), Generics::default())) + Ok((ident, TraitItemKind::Const(ty, expr), Generics::default())) } /// Parses the following grammar: diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index a078a36db7ac4..ba0e6b100eea6 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -259,12 +259,12 @@ impl<'a> AstValidator<'a> { !arr.contains(&attr.name_or_empty()) && attr::is_builtin_attr(attr) }) .for_each(|attr| if attr.is_doc_comment() { - let mut err = self.err_handler().struct_span_err( + self.err_handler().struct_span_err( attr.span, "documentation comments cannot be applied to function parameters" - ); - err.span_label(attr.span, "doc comments are not allowed here"); - err.emit(); + ) + .span_label(attr.span, "doc comments are not allowed here") + .emit(); } else { self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \ @@ -746,8 +746,22 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_impl_item(&mut self, ii: &'a ImplItem) { - if let ImplItemKind::Method(ref sig, _) = ii.kind { - self.check_fn_decl(&sig.decl); + match &ii.kind { + ImplItemKind::Const(ty, None) => { + self.err_handler() + .struct_span_err(ii.span, "associated constant in `impl` without body") + .span_suggestion( + ii.span, + "provide a definition for the constant", + format!("const {}: {} = ;", ii.ident, pprust::ty_to_string(ty)), + Applicability::HasPlaceholders, + ) + .emit(); + } + ImplItemKind::Method(sig, _) => { + self.check_fn_decl(&sig.decl); + } + _ => {} } visit::walk_impl_item(self, ii); } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 396d948433961..97cbcb6401c55 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1110,7 +1110,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { impl_item.id, impl_item.ident, &ty, - Some(expr), + expr.as_deref(), impl_id, impl_item.vis.clone(), &impl_item.attrs, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 964acfa92b9bb..17a57387da7bc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1635,8 +1635,8 @@ pub struct ImplItem { /// Represents various kinds of content within an `impl`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ImplItemKind { - Const(P, P), +pub enum ImplItemKind { + Const(P, Option>), Method(FnSig, P), TyAlias(P), Macro(Mac), diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 9d0a29f29511d..147014550138f 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -981,7 +981,7 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut match kind { ImplItemKind::Const(ty, expr) => { visitor.visit_ty(ty); - visitor.visit_expr(expr); + visit_opt(expr, |expr| visitor.visit_expr(expr)); } ImplItemKind::Method(sig, body) => { visit_fn_sig(sig, visitor); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 2e3ea5e24440f..c1405e15819a4 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1599,7 +1599,7 @@ impl<'a> State<'a> { self.print_defaultness(ii.defaultness); match ii.kind { ast::ImplItemKind::Const(ref ty, ref expr) => { - self.print_associated_const(ii.ident, ty, Some(expr), &ii.vis); + self.print_associated_const(ii.ident, ty, expr.as_deref(), &ii.vis); } ast::ImplItemKind::Method(ref sig, ref body) => { self.head(""); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4ee09b4b87afa..0b7a7d993aa98 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -617,7 +617,7 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt match impl_item.kind { ImplItemKind::Const(ref ty, ref expr) => { visitor.visit_ty(ty); - visitor.visit_expr(expr); + walk_list!(visitor, visit_expr, expr); } ImplItemKind::Method(ref sig, ref body) => { visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body), diff --git a/src/test/ui/parser/impl-item-const-pass.rs b/src/test/ui/parser/impl-item-const-pass.rs new file mode 100644 index 0000000000000..d1124561374a5 --- /dev/null +++ b/src/test/ui/parser/impl-item-const-pass.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + const Y: u8; +} diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.rs b/src/test/ui/parser/impl-item-const-semantic-fail.rs new file mode 100644 index 0000000000000..5d4692f9f14ac --- /dev/null +++ b/src/test/ui/parser/impl-item-const-semantic-fail.rs @@ -0,0 +1,7 @@ +fn main() {} + +struct X; + +impl X { + const Y: u8; //~ ERROR associated constant in `impl` without body +} diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.stderr b/src/test/ui/parser/impl-item-const-semantic-fail.stderr new file mode 100644 index 0000000000000..31a15f8e80e3d --- /dev/null +++ b/src/test/ui/parser/impl-item-const-semantic-fail.stderr @@ -0,0 +1,8 @@ +error: associated constant in `impl` without body + --> $DIR/impl-item-const-semantic-fail.rs:6:5 + | +LL | const Y: u8; + | ^^^^^^^^^^^^ help: provide a definition for the constant: `const Y: u8 = ;` + +error: aborting due to previous error + From f6403c6c766c704569564b9021071c4917d45a25 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 07:24:07 +0100 Subject: [PATCH 05/38] Use `Option` in `ImplItemKind::Method`. --- src/librustc/hir/lowering.rs | 4 +- src/librustc/hir/lowering/item.rs | 71 +++++++++++++------ src/librustc_parse/parser/item.rs | 12 ++-- src/librustc_passes/ast_validation.rs | 31 +++++--- src/librustc_resolve/def_collector.rs | 10 +-- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 26 +++---- src/libsyntax/visit.rs | 12 ++-- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- src/test/ui/issues/issue-58856-1.rs | 2 + src/test/ui/issues/issue-58856-1.stderr | 17 ++++- .../impl-item-const-semantic-fail.stderr | 4 +- .../ui/parser/impl-item-fn-no-body-pass.rs | 8 +++ .../impl-item-fn-no-body-semantic-fail.rs | 7 ++ .../impl-item-fn-no-body-semantic-fail.stderr | 10 +++ 17 files changed, 149 insertions(+), 73 deletions(-) create mode 100644 src/test/ui/parser/impl-item-fn-no-body-pass.rs create mode 100644 src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs create mode 100644 src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e13f6cabb5296..a82febba38ab0 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1211,7 +1211,7 @@ impl<'a> LoweringContext<'a> { let ct = self.with_new_scopes(|this| { hir::AnonConst { hir_id: this.lower_node_id(node_id), - body: this.lower_const_body(&path_expr), + body: this.lower_const_body(path_expr.span, Some(&path_expr)), } }); return GenericArg::Const(ConstArg { @@ -3003,7 +3003,7 @@ impl<'a> LoweringContext<'a> { self.with_new_scopes(|this| { hir::AnonConst { hir_id: this.lower_node_id(c.id), - body: this.lower_const_body(&c.value), + body: this.lower_const_body(c.value.span, Some(&c.value)), } }) } diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 32b36d2021b0f..7e231cd6b5982 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -250,7 +250,7 @@ impl LoweringContext<'_> { return None; } - let kind = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.kind); + let kind = self.lower_item_kind(i.span, i.id, &mut ident, &attrs, &mut vis, &i.kind); Some(hir::Item { hir_id: self.lower_node_id(i.id), @@ -264,6 +264,7 @@ impl LoweringContext<'_> { fn lower_item_kind( &mut self, + span: Span, id: NodeId, ident: &mut Ident, attrs: &hir::HirVec, @@ -292,7 +293,7 @@ impl LoweringContext<'_> { } ), m, - self.lower_const_body(e), + self.lower_const_body(span, Some(e)), ) } ItemKind::Const(ref t, ref e) => { @@ -305,7 +306,7 @@ impl LoweringContext<'_> { ImplTraitContext::Disallowed(ImplTraitPosition::Binding) } ), - self.lower_const_body(e) + self.lower_const_body(span, Some(e)) ) } ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => { @@ -317,7 +318,12 @@ impl LoweringContext<'_> { // `impl Future` here because lower_body // only cares about the input argument patterns in the function // declaration (decl), not the return types. - let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body); + let body_id = this.lower_maybe_async_body( + span, + &decl, + header.asyncness.node, + Some(body), + ); let (generics, decl) = this.add_in_band_defs( generics, @@ -817,7 +823,7 @@ impl LoweringContext<'_> { self.lower_ty(ty, ImplTraitContext::disallowed()), default .as_ref() - .map(|x| self.lower_const_body(x)), + .map(|x| self.lower_const_body(i.span, Some(x))), ), ), TraitItemKind::Method(ref sig, None) => { @@ -832,7 +838,7 @@ impl LoweringContext<'_> { (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } TraitItemKind::Method(ref sig, Some(ref body)) => { - let body_id = self.lower_fn_body_block(&sig.decl, body); + let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = self.lower_method_sig( &i.generics, sig, @@ -891,6 +897,11 @@ impl LoweringContext<'_> { } } + /// Construct `ExprKind::Err` for the given `span`. + fn expr_err(&mut self, span: Span) -> hir::Expr { + self.expr(span, hir::ExprKind::Err, ThinVec::new()) + } + fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem { let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); @@ -899,19 +910,16 @@ impl LoweringContext<'_> { self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::ImplItemKind::Const( self.lower_ty(ty, ImplTraitContext::disallowed()), - match expr { - Some(expr) => self.lower_const_body(expr), - None => self.lower_body(|this| ( - hir_vec![], - this.expr(i.span, hir::ExprKind::Err, ThinVec::new()), - )), - } + self.lower_const_body(i.span, expr.as_deref()), ), ), ImplItemKind::Method(ref sig, ref body) => { self.current_item = Some(i.span); let body_id = self.lower_maybe_async_body( - &sig.decl, sig.header.asyncness.node, body + i.span, + &sig.decl, + sig.header.asyncness.node, + body.as_deref(), ); let impl_trait_return_allow = !self.is_in_trait_impl; let (generics, sig) = self.lower_method_sig( @@ -1069,23 +1077,39 @@ impl LoweringContext<'_> { )) } - fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId { - self.lower_fn_body(decl, |this| this.lower_block_expr(body)) + fn lower_fn_body_block( + &mut self, + span: Span, + decl: &FnDecl, + body: Option<&Block>, + ) -> hir::BodyId { + self.lower_fn_body(decl, |this| this.lower_block_expr_opt(span, body)) + } + + fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr { + match block { + Some(block) => self.lower_block_expr(block), + None => self.expr_err(span), + } } - pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId { - self.lower_body(|this| (hir_vec![], this.lower_expr(expr))) + pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId { + self.lower_body(|this| (hir_vec![], match expr { + Some(expr) => this.lower_expr(expr), + None => this.expr_err(span), + })) } fn lower_maybe_async_body( &mut self, + span: Span, decl: &FnDecl, asyncness: IsAsync, - body: &Block, + body: Option<&Block>, ) -> hir::BodyId { let closure_id = match asyncness { IsAsync::Async { closure_id, .. } => closure_id, - IsAsync::NotAsync => return self.lower_fn_body_block(decl, body), + IsAsync::NotAsync => return self.lower_fn_body_block(span, decl, body), }; self.lower_body(|this| { @@ -1219,15 +1243,16 @@ impl LoweringContext<'_> { parameters.push(new_parameter); } + let body_span = body.map_or(span, |b| b.span); let async_expr = this.make_async_expr( CaptureBy::Value, closure_id, None, - body.span, + body_span, hir::AsyncGeneratorKind::Fn, |this| { // Create a block from the user's function body: - let user_body = this.lower_block_expr(body); + let user_body = this.lower_block_expr_opt(body_span, body); // Transform into `drop-temps { }`, an expression: let desugared_span = this.mark_span_with_reason( @@ -1257,7 +1282,7 @@ impl LoweringContext<'_> { ); this.expr_block(P(body), ThinVec::new()) }); - (HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new())) + (HirVec::from(parameters), this.expr(body_span, async_expr, ThinVec::new())) }) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 68fdfd24d6164..053502c43dcde 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -705,9 +705,7 @@ impl<'a> Parser<'a> { // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default()) } else { - let (name, inner_attrs, generics, kind) = self.parse_impl_method(at_end)?; - attrs.extend(inner_attrs); - (name, kind, generics) + self.parse_impl_method(at_end, &mut attrs)? }; Ok(ImplItem { @@ -1842,11 +1840,11 @@ impl<'a> Parser<'a> { fn parse_impl_method( &mut self, at_end: &mut bool, - ) -> PResult<'a, (Ident, Vec, Generics, ImplItemKind)> { + attrs: &mut Vec, + ) -> PResult<'a, (Ident, ImplItemKind, Generics)> { let (ident, sig, generics) = self.parse_method_sig(|_| true)?; - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body))) + let body = self.parse_trait_method_body(at_end, attrs)?; + Ok((ident, ast::ImplItemKind::Method(sig, body), generics)) } fn parse_trait_item_method( diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index ba0e6b100eea6..78866dc9cc90a 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -279,6 +279,22 @@ impl<'a> AstValidator<'a> { .emit(); } } + + fn check_impl_item_provided(&self, sp: Span, body: &Option, ctx: &str, sugg: &str) { + if body.is_some() { + return; + } + + self.err_handler() + .struct_span_err(sp, &format!("associated {} in `impl` without body", ctx)) + .span_suggestion( + self.session.source_map().end_point(sp), + &format!("provide a definition for the {}", ctx), + sugg.to_string(), + Applicability::HasPlaceholders, + ) + .emit(); + } } enum GenericPosition { @@ -747,18 +763,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { match &ii.kind { - ImplItemKind::Const(ty, None) => { - self.err_handler() - .struct_span_err(ii.span, "associated constant in `impl` without body") - .span_suggestion( - ii.span, - "provide a definition for the constant", - format!("const {}: {} = ;", ii.ident, pprust::ty_to_string(ty)), - Applicability::HasPlaceholders, - ) - .emit(); + ImplItemKind::Const(_, body) => { + self.check_impl_item_provided(ii.span, body, "constant", " = ;"); } - ImplItemKind::Method(sig, _) => { + ImplItemKind::Method(sig, body) => { + self.check_impl_item_provided(ii.span, body, "function", " { }"); self.check_fn_decl(&sig.decl); } _ => {} diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index dd6b1d2119e3d..76a52bb7f7f37 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -50,7 +50,7 @@ impl<'a> DefCollector<'a> { header: &FnHeader, generics: &'a Generics, decl: &'a FnDecl, - body: &'a Block, + body: Option<&'a Block>, ) { let (closure_id, return_impl_trait_id) = match header.asyncness.node { IsAsync::Async { @@ -74,7 +74,9 @@ impl<'a> DefCollector<'a> { closure_id, DefPathData::ClosureExpr, span, ); this.with_parent(closure_def, |this| { - visit::walk_block(this, body); + if let Some(body) = body { + visit::walk_block(this, body); + } }) }) } @@ -123,7 +125,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { &sig.header, generics, &sig.decl, - body, + Some(body), ) } ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => @@ -237,7 +239,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { header, &ii.generics, decl, - body, + body.as_deref(), ) } ImplItemKind::Method(..) | diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 97cbcb6401c55..99f9c3b1f2e32 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1119,7 +1119,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ast::ImplItemKind::Method(ref sig, ref body) => { self.process_method( sig, - Some(body), + body.as_deref(), impl_item.id, impl_item.ident, &impl_item.generics, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 17a57387da7bc..f6af5d8637edc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1637,7 +1637,7 @@ pub struct ImplItem { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ImplItemKind { Const(P, Option>), - Method(FnSig, P), + Method(FnSig, Option>), TyAlias(P), Macro(Mac), } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 147014550138f..0fa4dcf3ad9dd 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -985,7 +985,7 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut } ImplItemKind::Method(sig, body) => { visit_fn_sig(sig, visitor); - visitor.visit_block(body); + visit_opt(body, |body| visitor.visit_block(body)); } ImplItemKind::TyAlias(ty) => visitor.visit_ty(ty), ImplItemKind::Macro(mac) => visitor.visit_mac(mac), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c1405e15819a4..34097841b4ac9 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1553,23 +1553,13 @@ impl<'a> State<'a> { self.print_defaultness(ti.defaultness); match ti.kind { ast::TraitItemKind::Const(ref ty, ref default) => { - self.print_associated_const( - ti.ident, - ty, - default.as_ref().map(|expr| &**expr), - &source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited), - ); + self.print_associated_const(ti.ident, ty, default.as_deref(), &ti.vis); } ast::TraitItemKind::Method(ref sig, ref body) => { if body.is_some() { self.head(""); } - self.print_method_sig( - ti.ident, - &ti.generics, - sig, - &source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited), - ); + self.print_method_sig(ti.ident, &ti.generics, sig, &ti.vis); if let Some(ref body) = *body { self.nbsp(); self.print_block_with_attrs(body, &ti.attrs); @@ -1602,10 +1592,16 @@ impl<'a> State<'a> { self.print_associated_const(ii.ident, ty, expr.as_deref(), &ii.vis); } ast::ImplItemKind::Method(ref sig, ref body) => { - self.head(""); + if body.is_some() { + self.head(""); + } self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis); - self.nbsp(); - self.print_block_with_attrs(body, &ii.attrs); + if let Some(body) = body { + self.nbsp(); + self.print_block_with_attrs(body, &ii.attrs); + } else { + self.s.word(";"); + } } ast::ImplItemKind::TyAlias(ref ty) => { self.print_associated_type(ii.ident, None, Some(ty)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 0b7a7d993aa98..bdf70ec46f7d3 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -25,7 +25,7 @@ pub enum FnKind<'a> { ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block), /// E.g., `fn foo(&self)`. - Method(Ident, &'a FnSig, Option<&'a Visibility>, &'a Block), + Method(Ident, &'a FnSig, &'a Visibility, &'a Block), /// E.g., `|x, y| body`. Closure(&'a Expr), @@ -596,7 +596,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai walk_fn_decl(visitor, &sig.decl); } TraitItemKind::Method(ref sig, Some(ref body)) => { - visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None, body), + visitor.visit_fn(FnKind::Method(trait_item.ident, sig, &trait_item.vis, body), &sig.decl, trait_item.span, trait_item.id); } TraitItemKind::Type(ref bounds, ref default) => { @@ -619,8 +619,12 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - ImplItemKind::Method(ref sig, ref body) => { - visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body), + ImplItemKind::Method(ref sig, None) => { + visitor.visit_fn_header(&sig.header); + walk_fn_decl(visitor, &sig.decl); + } + ImplItemKind::Method(ref sig, Some(ref body)) => { + visitor.visit_fn(FnKind::Method(impl_item.ident, sig, &impl_item.vis, body), &sig.decl, impl_item.span, impl_item.id); } ImplItemKind::TyAlias(ref ty) => { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 5bd84b43a7801..e8c4f993d4f34 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -956,7 +956,7 @@ impl<'a> MethodDef<'a> { vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, ident: method_ident, - kind: ast::ImplItemKind::Method(sig, body_block), + kind: ast::ImplItemKind::Method(sig, Some(body_block)), tokens: None, } } diff --git a/src/test/ui/issues/issue-58856-1.rs b/src/test/ui/issues/issue-58856-1.rs index db3984cd18987..8b1a39a94e67a 100644 --- a/src/test/ui/issues/issue-58856-1.rs +++ b/src/test/ui/issues/issue-58856-1.rs @@ -1,6 +1,8 @@ impl A { + //~^ ERROR cannot find type `A` in this scope fn b(self> //~^ ERROR expected one of `)`, `,`, or `:`, found `>` + //~| ERROR expected `;` or `{`, found `>` } fn main() {} diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr index 58ab0a142d6f1..0ea6b01754890 100644 --- a/src/test/ui/issues/issue-58856-1.stderr +++ b/src/test/ui/issues/issue-58856-1.stderr @@ -1,10 +1,23 @@ error: expected one of `)`, `,`, or `:`, found `>` - --> $DIR/issue-58856-1.rs:2:14 + --> $DIR/issue-58856-1.rs:3:14 | LL | fn b(self> | - ^ help: `)` may belong here | | | unclosed delimiter -error: aborting due to previous error +error: expected `;` or `{`, found `>` + --> $DIR/issue-58856-1.rs:3:14 + | +LL | fn b(self> + | ^ expected `;` or `{` + +error[E0412]: cannot find type `A` in this scope + --> $DIR/issue-58856-1.rs:1:6 + | +LL | impl A { + | ^ not found in this scope + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.stderr b/src/test/ui/parser/impl-item-const-semantic-fail.stderr index 31a15f8e80e3d..ec3bee0ce6824 100644 --- a/src/test/ui/parser/impl-item-const-semantic-fail.stderr +++ b/src/test/ui/parser/impl-item-const-semantic-fail.stderr @@ -2,7 +2,9 @@ error: associated constant in `impl` without body --> $DIR/impl-item-const-semantic-fail.rs:6:5 | LL | const Y: u8; - | ^^^^^^^^^^^^ help: provide a definition for the constant: `const Y: u8 = ;` + | ^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` error: aborting due to previous error diff --git a/src/test/ui/parser/impl-item-fn-no-body-pass.rs b/src/test/ui/parser/impl-item-fn-no-body-pass.rs new file mode 100644 index 0000000000000..16b09d64e8c17 --- /dev/null +++ b/src/test/ui/parser/impl-item-fn-no-body-pass.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + fn f(); +} diff --git a/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs new file mode 100644 index 0000000000000..cb183db59643e --- /dev/null +++ b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs @@ -0,0 +1,7 @@ +fn main() {} + +struct X; + +impl X { + fn f(); //~ ERROR associated function in `impl` without body +} diff --git a/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr new file mode 100644 index 0000000000000..1acb727368bce --- /dev/null +++ b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr @@ -0,0 +1,10 @@ +error: associated function in `impl` without body + --> $DIR/impl-item-fn-no-body-semantic-fail.rs:6:5 + | +LL | fn f(); + | ^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: aborting due to previous error + From c02fd3130284921f7077f78271b5501b402ec469 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 08:41:35 +0100 Subject: [PATCH 06/38] `TraitItemKind::Type` -> `TraitItemKind::TyAlias`. --- src/librustc/hir/lowering/item.rs | 4 ++-- src/librustc_parse/parser/item.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/def_collector.rs | 2 +- src/librustc_resolve/late.rs | 4 ++-- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/feature_gate/check.rs | 2 +- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 7e231cd6b5982..ec78bcf140313 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -848,7 +848,7 @@ impl LoweringContext<'_> { ); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) } - TraitItemKind::Type(ref bounds, ref default) => { + TraitItemKind::TyAlias(ref bounds, ref default) => { let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); let kind = hir::TraitItemKind::Type( self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), @@ -877,7 +877,7 @@ impl LoweringContext<'_> { TraitItemKind::Const(_, ref default) => { (hir::AssocItemKind::Const, default.is_some()) } - TraitItemKind::Type(_, ref default) => { + TraitItemKind::TyAlias(_, ref default) => { (hir::AssocItemKind::Type, default.is_some()) } TraitItemKind::Method(ref sig, ref default) => ( diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 053502c43dcde..5bfecf78e71cc 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -944,7 +944,7 @@ impl<'a> Parser<'a> { }; self.expect_semi()?; - Ok((ident, TraitItemKind::Type(bounds, default), generics)) + Ok((ident, TraitItemKind::TyAlias(bounds, default), generics)) } /// Parses a `UseTree`. diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e2578d67e730c..d2d5a33ec7aa9 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1182,7 +1182,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { } (Res::Def(DefKind::Method, item_def_id), ValueNS) } - TraitItemKind::Type(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS), + TraitItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS), TraitItemKind::Macro(_) => bug!(), // handled above }; diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 76a52bb7f7f37..471e2634b8acf 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -216,7 +216,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def_data = match ti.kind { TraitItemKind::Method(..) | TraitItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name), - TraitItemKind::Type(..) => { + TraitItemKind::TyAlias(..) => { DefPathData::TypeNs(ti.ident.name) }, TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 4f95d6fe70f17..d32a6a4b3e6b3 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -821,7 +821,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { TraitItemKind::Method(_, _) => { visit::walk_trait_item(this, trait_item) } - TraitItemKind::Type(..) => { + TraitItemKind::TyAlias(..) => { visit::walk_trait_item(this, trait_item) } TraitItemKind::Macro(_) => { @@ -995,7 +995,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { let trait_assoc_types = replace( &mut self.diagnostic_metadata.current_trait_assoc_types, trait_items.iter().filter_map(|item| match &item.kind { - TraitItemKind::Type(bounds, _) if bounds.len() == 0 => Some(item.ident), + TraitItemKind::TyAlias(bounds, _) if bounds.len() == 0 => Some(item.ident), _ => None, }).collect(), ); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 99f9c3b1f2e32..bd7851296ddc2 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1056,7 +1056,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { trait_item.span, ); } - ast::TraitItemKind::Type(ref bounds, ref default_ty) => { + ast::TraitItemKind::TyAlias(ref bounds, ref default_ty) => { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!("::{}", diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f6af5d8637edc..4e2f78e8ab8ea 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1613,7 +1613,7 @@ pub type TraitItem = ImplItem; pub enum TraitItemKind { Const(P, Option>), Method(FnSig, Option>), - Type(GenericBounds, Option>), + TyAlias(GenericBounds, Option>), Macro(Mac), } diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 3d2c3b1d4f901..10f6bbb594911 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -585,7 +585,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); } } - ast::TraitItemKind::Type(_, ref default) => { + ast::TraitItemKind::TyAlias(_, ref default) => { if let Some(ty) = default { self.check_impl_trait(ty); gate_feature_post!(&self, associated_type_defaults, ti.span, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 0fa4dcf3ad9dd..66cac0f917d93 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -955,7 +955,7 @@ pub fn noop_flat_map_trait_item(mut item: TraitItem, visitor: &mu visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - TraitItemKind::Type(bounds, default) => { + TraitItemKind::TyAlias(bounds, default) => { visit_bounds(bounds, visitor); visit_opt(default, |default| visitor.visit_ty(default)); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 34097841b4ac9..00dcd7e8d0b6f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1567,7 +1567,7 @@ impl<'a> State<'a> { self.s.word(";"); } } - ast::TraitItemKind::Type(ref bounds, ref default) => { + ast::TraitItemKind::TyAlias(ref bounds, ref default) => { self.print_associated_type(ti.ident, Some(bounds), default.as_ref().map(|ty| &**ty)); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index bdf70ec46f7d3..f96290ec4f8ed 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -599,7 +599,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai visitor.visit_fn(FnKind::Method(trait_item.ident, sig, &trait_item.vis, body), &sig.decl, trait_item.span, trait_item.id); } - TraitItemKind::Type(ref bounds, ref default) => { + TraitItemKind::TyAlias(ref bounds, ref default) => { walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, default); } From 39073767a483d10f8b4b2ac2f32bc9573d9dabbf Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:25:45 +0100 Subject: [PATCH 07/38] Unify `{Trait,Impl}ItemKind::TyAlias` structures. --- src/librustc/hir/lowering.rs | 37 ++++------ src/librustc/hir/lowering/item.rs | 24 ++++-- src/librustc_parse/parser/item.rs | 30 +++++++- src/librustc_passes/ast_validation.rs | 15 ++++ src/librustc_passes/lib.rs | 1 + src/librustc_resolve/late.rs | 3 +- src/librustc_save_analysis/dump_visitor.rs | 3 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/feature_gate/check.rs | 6 +- src/libsyntax/mut_visit.rs | 5 +- src/libsyntax/print/pprust.rs | 22 +++--- src/libsyntax/visit.rs | 5 +- src/libsyntax_ext/deriving/generic/mod.rs | 4 +- .../ui/parser/impl-item-type-no-body-pass.rs | 11 +++ .../impl-item-type-no-body-semantic-fail.rs | 22 ++++++ ...mpl-item-type-no-body-semantic-fail.stderr | 73 +++++++++++++++++++ 16 files changed, 209 insertions(+), 54 deletions(-) create mode 100644 src/test/ui/parser/impl-item-type-no-body-pass.rs create mode 100644 src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs create mode 100644 src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a82febba38ab0..54ff1f56eec0d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1253,6 +1253,14 @@ impl<'a> LoweringContext<'a> { ty } + fn ty(&mut self, span: Span, kind: hir::TyKind) -> hir::Ty { + hir::Ty { hir_id: self.next_id(), kind, span } + } + + fn ty_tup(&mut self, span: Span, tys: HirVec) -> hir::Ty { + self.ty(span, hir::TyKind::Tup(tys)) + } + fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, @@ -2084,12 +2092,9 @@ impl<'a> LoweringContext<'a> { .iter() .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())) .collect(); - let mk_tup = |this: &mut Self, tys, span| { - hir::Ty { kind: hir::TyKind::Tup(tys), hir_id: this.next_id(), span } - }; ( hir::GenericArgs { - args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))], + args: hir_vec![GenericArg::Type(this.ty_tup(span, inputs))], bindings: hir_vec![ hir::TypeBinding { hir_id: this.next_id(), @@ -2102,7 +2107,7 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::disallowed() )) .unwrap_or_else(|| - P(mk_tup(this, hir::HirVec::new(), span)) + P(this.ty_tup(span, hir::HirVec::new())) ), }, span: output.as_ref().map_or(span, |ty| ty.span), @@ -2474,17 +2479,13 @@ impl<'a> LoweringContext<'a> { }) ); - // Create the `Foo<...>` refernece itself. Note that the `type + // Create the `Foo<...>` reference itself. Note that the `type // Foo = impl Trait` is, internally, created as a child of the // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into()); - - hir::FunctionRetTy::Return(P(hir::Ty { - kind: opaque_ty_ref, - span: opaque_ty_span, - hir_id: self.next_id(), - })) + let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref); + hir::FunctionRetTy::Return(P(opaque_ty)) } /// Transforms `-> T` into `Future` @@ -2496,16 +2497,8 @@ impl<'a> LoweringContext<'a> { ) -> hir::GenericBound { // Compute the `T` in `Future` from the return type. let output_ty = match output { - FunctionRetTy::Ty(ty) => { - self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))) - } - FunctionRetTy::Default(ret_ty_span) => { - P(hir::Ty { - hir_id: self.next_id(), - kind: hir::TyKind::Tup(hir_vec![]), - span: *ret_ty_span, - }) - } + FunctionRetTy::Ty(ty) => self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))), + FunctionRetTy::Default(ret_ty_span) => P(self.ty_tup(*ret_ty_span, hir_vec![])), }; // "" diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index ec78bcf140313..f77523e638275 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -932,16 +932,21 @@ impl LoweringContext<'_> { (generics, hir::ImplItemKind::Method(sig, body_id)) } - ImplItemKind::TyAlias(ref ty) => { + ImplItemKind::TyAlias(_, ref ty) => { let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); - let kind = match ty.kind.opaque_top_hack() { + let kind = match ty { None => { - let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); - hir::ImplItemKind::TyAlias(ty) + hir::ImplItemKind::TyAlias(P(self.ty(i.span, hir::TyKind::Err))) } - Some(bs) => { - let bounds = self.lower_param_bounds(bs, ImplTraitContext::disallowed()); - hir::ImplItemKind::OpaqueTy(bounds) + Some(ty) => match ty.kind.opaque_top_hack() { + None => { + let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); + hir::ImplItemKind::TyAlias(ty) + } + Some(bs) => { + let bs = self.lower_param_bounds(bs, ImplTraitContext::disallowed()); + hir::ImplItemKind::OpaqueTy(bs) + } } }; (generics, kind) @@ -972,7 +977,10 @@ impl LoweringContext<'_> { defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), kind: match &i.kind { ImplItemKind::Const(..) => hir::AssocItemKind::Const, - ImplItemKind::TyAlias(ty) => match ty.kind.opaque_top_hack() { + ImplItemKind::TyAlias(_, ty) => match ty + .as_deref() + .and_then(|ty| ty.kind.opaque_top_hack()) + { None => hir::AssocItemKind::Type, Some(_) => hir::AssocItemKind::OpaqueTy, }, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 5bfecf78e71cc..302fcba4cf876 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -697,8 +697,7 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { - let (name, ty, generics) = self.parse_type_alias()?; - (name, ast::ImplItemKind::TyAlias(ty), generics) + self.parse_impl_assoc_ty()? } else if self.is_const_item() { self.parse_impl_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? { @@ -766,6 +765,31 @@ impl<'a> Parser<'a> { Ok((ident, ImplItemKind::Const(ty, expr), Generics::default())) } + /// Parses the following grammar: + /// + /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] + fn parse_impl_assoc_ty(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { + let ident = self.parse_ident()?; + let mut generics = self.parse_generics()?; + + // Parse optional colon and param bounds. + let bounds = if self.eat(&token::Colon) { + self.parse_generic_bounds(None)? + } else { + Vec::new() + }; + generics.where_clause = self.parse_where_clause()?; + + let default = if self.eat(&token::Eq) { + Some(self.parse_ty()?) + } else { + None + }; + self.expect_semi()?; + + Ok((ident, ImplItemKind::TyAlias(bounds, default), generics)) + } + /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. @@ -924,7 +948,7 @@ impl<'a> Parser<'a> { /// Parses the following grammar: /// - /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] + /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 78866dc9cc90a..f4b28077e9f02 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -295,6 +295,17 @@ impl<'a> AstValidator<'a> { ) .emit(); } + + fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) { + let span = match bounds { + [] => return, + [b0] => b0.span(), + [b0, .., bl] => b0.span().to(bl.span()), + }; + self.err_handler() + .struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect") + .emit(); + } } enum GenericPosition { @@ -770,6 +781,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_impl_item_provided(ii.span, body, "function", " { }"); self.check_fn_decl(&sig.decl); } + ImplItemKind::TyAlias(bounds, body) => { + self.check_impl_item_provided(ii.span, body, "type", " = ;"); + self.check_impl_assoc_type_no_bounds(bounds); + } _ => {} } visit::walk_impl_item(self, ii); diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 81f06a14d95f5..f01867f32c67b 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -8,6 +8,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] +#![feature(slice_patterns)] #![recursion_limit="256"] diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index d32a6a4b3e6b3..33e24c8cfd4a7 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1119,7 +1119,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { visit::walk_impl_item(this, impl_item); } - ImplItemKind::TyAlias(ref ty) => { + ImplItemKind::TyAlias(_, Some(ref ty)) => { // If this is a trait impl, ensure the type // exists in trait this.check_trait_item(impl_item.ident, @@ -1129,6 +1129,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { this.visit_ty(ty); } + ImplItemKind::TyAlias(_, None) => {} ImplItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index bd7851296ddc2..d63a9df8d9bc4 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1127,7 +1127,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { impl_item.span, ); } - ast::ImplItemKind::TyAlias(ref ty) => { + ast::ImplItemKind::TyAlias(_, None) => {} + ast::ImplItemKind::TyAlias(_, Some(ref ty)) => { // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 4e2f78e8ab8ea..89868a9cd294c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1638,7 +1638,7 @@ pub struct ImplItem { pub enum ImplItemKind { Const(P, Option>), Method(FnSig, Option>), - TyAlias(P), + TyAlias(GenericBounds, Option>), Macro(Mac), } diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 10f6bbb594911..f786de6401a6e 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -612,8 +612,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "C-variadic functions are unstable"); } } - ast::ImplItemKind::TyAlias(ref ty) => { - self.check_impl_trait(ty); + ast::ImplItemKind::TyAlias(_, ref ty) => { + if let Some(ty) = ty { + self.check_impl_trait(ty); + } self.check_gat(&ii.generics, ii.span); } _ => {} diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 66cac0f917d93..bb0462c19cdff 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -987,7 +987,10 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - ImplItemKind::TyAlias(ty) => visitor.visit_ty(ty), + ImplItemKind::TyAlias(bounds, ty) => { + visit_bounds(bounds, visitor); + visit_opt(ty, |ty| visitor.visit_ty(ty)); + } ImplItemKind::Macro(mac) => visitor.visit_mac(mac), } visitor.visit_span(span); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 00dcd7e8d0b6f..03e394b8c7e9c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1128,16 +1128,15 @@ impl<'a> State<'a> { self.s.word(";") } - fn print_associated_type(&mut self, - ident: ast::Ident, - bounds: Option<&ast::GenericBounds>, - ty: Option<&ast::Ty>) - { + fn print_associated_type( + &mut self, + ident: ast::Ident, + bounds: &ast::GenericBounds, + ty: Option<&ast::Ty>, + ) { self.word_space("type"); self.print_ident(ident); - if let Some(bounds) = bounds { - self.print_type_bounds(":", bounds); - } + self.print_type_bounds(":", bounds); if let Some(ty) = ty { self.s.space(); self.word_space("="); @@ -1568,8 +1567,7 @@ impl<'a> State<'a> { } } ast::TraitItemKind::TyAlias(ref bounds, ref default) => { - self.print_associated_type(ti.ident, Some(bounds), - default.as_ref().map(|ty| &**ty)); + self.print_associated_type(ti.ident, bounds, default.as_deref()); } ast::TraitItemKind::Macro(ref mac) => { self.print_mac(mac); @@ -1603,8 +1601,8 @@ impl<'a> State<'a> { self.s.word(";"); } } - ast::ImplItemKind::TyAlias(ref ty) => { - self.print_associated_type(ii.ident, None, Some(ty)); + ast::ImplItemKind::TyAlias(ref bounds, ref ty) => { + self.print_associated_type(ii.ident, bounds, ty.as_deref()); } ast::ImplItemKind::Macro(ref mac) => { self.print_mac(mac); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index f96290ec4f8ed..7cc1a769e52bf 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -627,8 +627,9 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt visitor.visit_fn(FnKind::Method(impl_item.ident, sig, &impl_item.vis, body), &sig.decl, impl_item.span, impl_item.id); } - ImplItemKind::TyAlias(ref ty) => { - visitor.visit_ty(ty); + ImplItemKind::TyAlias(ref bounds, ref ty) => { + walk_list!(visitor, visit_param_bound, bounds); + walk_list!(visitor, visit_ty, ty); } ImplItemKind::Macro(ref mac) => { visitor.visit_mac(mac); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index e8c4f993d4f34..d51fcf315a69b 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -519,7 +519,9 @@ impl<'a> TraitDef<'a> { attrs: Vec::new(), generics: Generics::default(), kind: ast::ImplItemKind::TyAlias( - type_def.to_ty(cx, self.span, type_ident, generics)), + Vec::new(), + Some(type_def.to_ty(cx, self.span, type_ident, generics)), + ), tokens: None, } }); diff --git a/src/test/ui/parser/impl-item-type-no-body-pass.rs b/src/test/ui/parser/impl-item-type-no-body-pass.rs new file mode 100644 index 0000000000000..74a9c6ab7e8a6 --- /dev/null +++ b/src/test/ui/parser/impl-item-type-no-body-pass.rs @@ -0,0 +1,11 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + type Y; + type Z: Ord; + type W: Ord where Self: Eq; + type W where Self: Eq; +} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs new file mode 100644 index 0000000000000..71c7d4ba21db6 --- /dev/null +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] +//~^ WARN the feature `generic_associated_types` is incomplete + +fn main() {} + +struct X; + +impl X { + type Y; + //~^ ERROR associated type in `impl` without body + //~| ERROR associated types are not yet supported in inherent impls + type Z: Ord; + //~^ ERROR associated type in `impl` without body + //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR associated types are not yet supported in inherent impls + type W: Ord where Self: Eq; + //~^ ERROR associated type in `impl` without body + //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR associated types are not yet supported in inherent impls + type W where Self: Eq; + //~^ ERROR associated type in `impl` without body +} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr new file mode 100644 index 0000000000000..6f1439c8f0b29 --- /dev/null +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -0,0 +1,73 @@ +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + | +LL | type Y; + | ^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5 + | +LL | type Z: Ord; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on associated `type`s in `impl`s have no effect + --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13 + | +LL | type Z: Ord; + | ^^^ + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5 + | +LL | type W: Ord where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on associated `type`s in `impl`s have no effect + --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:13 + | +LL | type W: Ord where Self: Eq; + | ^^^ + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5 + | +LL | type W where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash + --> $DIR/impl-item-type-no-body-semantic-fail.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0202]: associated types are not yet supported in inherent impls (see #8995) + --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + | +LL | type Y; + | ^^^^^^^ + +error[E0202]: associated types are not yet supported in inherent impls (see #8995) + --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5 + | +LL | type Z: Ord; + | ^^^^^^^^^^^^ + +error[E0202]: associated types are not yet supported in inherent impls (see #8995) + --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5 + | +LL | type W: Ord where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0202`. From 92a372b0204a5f18286ff94648b98e4c0d6d27d2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:46:06 +0100 Subject: [PATCH 08/38] Unify `{Impl,Trait}Item` as `AssocItem`. --- src/libsyntax/ast.rs | 41 +++++++++++++++++++++++---------------- src/libsyntax/attr/mod.rs | 2 +- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 89868a9cd294c..dd8a7fa8665c2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1603,23 +1603,16 @@ pub struct FnSig { pub decl: P, } -pub type TraitItem = ImplItem; +// FIXME(Centril): Remove all of these. +pub type TraitItem = AssocItem; +pub type TraitItemKind = AssocItemKind; +pub type ImplItem = AssocItem; +pub type ImplItemKind = AssocItemKind; -/// Represents the kind of an item declaration within a trait declaration, -/// possibly including a default implementation. A trait item is -/// either required (meaning it doesn't have an implementation, just a -/// signature) or provided (meaning it has a default implementation). +/// Represents associated items. +/// These include items in `impl` and `trait` definitions. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum TraitItemKind { - Const(P, Option>), - Method(FnSig, Option>), - TyAlias(GenericBounds, Option>), - Macro(Mac), -} - -/// Represents anything within an `impl` block. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct ImplItem { +pub struct AssocItem { pub attrs: Vec, pub id: NodeId, pub span: Span, @@ -1634,11 +1627,25 @@ pub struct ImplItem { } /// Represents various kinds of content within an `impl`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ImplItemKind { +/// +/// The term "provided" in the variants below refers to the item having a default +/// definition / body. Meanwhile, a "required" item lacks a definition / body. +/// In an implementation, all items must be provided. +/// The `Option`s below denote the bodies, where `Some(_)` +/// means "provided" and conversely `None` means "required". +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum AssocItemKind { + /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. + /// If `def` is parsed, then the associated constant is provided, and otherwise required. Const(P, Option>), + + /// An associated function. Method(FnSig, Option>), + + /// An associated type. TyAlias(GenericBounds, Option>), + + /// A macro expanding to an associated item. Macro(Mac), } diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 079a0f6fafa2c..13a9ed5f215d2 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -749,6 +749,6 @@ macro_rules! derive_has_attrs { } derive_has_attrs! { - Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, + Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::AssocItem, ast::Arm, ast::Field, ast::FieldPat, ast::Variant, ast::Param } From 2d92aa5535e9b28f4c9244785baed719b72b9d59 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:53:20 +0100 Subject: [PATCH 09/38] Fuse associated constant parsing. --- src/librustc_parse/parser/item.rs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 302fcba4cf876..d07fe358272c6 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -7,6 +7,7 @@ use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey}; use rustc_error_codes::*; use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind}; +use syntax::ast::{AssocItemKind}; use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit}; use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField}; @@ -699,7 +700,7 @@ impl<'a> Parser<'a> { let (name, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_impl_assoc_ty()? } else if self.is_const_item() { - self.parse_impl_const()? + self.parse_assoc_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? { // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default()) @@ -749,22 +750,6 @@ impl<'a> Parser<'a> { !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) } - /// This parses the grammar: - /// ImplItemConst = "const" Ident ":" Ty "=" Expr ";" - fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { - self.expect_keyword(kw::Const)?; - let ident = self.parse_ident()?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; - let expr = if self.eat(&token::Eq) { - Some(self.parse_expr()?) - } else { - None - }; - self.expect_semi()?; - Ok((ident, ImplItemKind::Const(ty, expr), Generics::default())) - } - /// Parses the following grammar: /// /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] @@ -911,7 +896,7 @@ impl<'a> Parser<'a> { let (name, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { - self.parse_trait_item_const()? + self.parse_assoc_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { // trait item macro. (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default()) @@ -932,7 +917,10 @@ impl<'a> Parser<'a> { }) } - fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { + /// This parses the grammar: + /// + /// AssocConst = "const" Ident ":" Ty "=" Expr ";" + fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> { self.expect_keyword(kw::Const)?; let ident = self.parse_ident()?; self.expect(&token::Colon)?; @@ -943,7 +931,7 @@ impl<'a> Parser<'a> { None }; self.expect_semi()?; - Ok((ident, TraitItemKind::Const(ty, expr), Generics::default())) + Ok((ident, AssocItemKind::Const(ty, expr), Generics::default())) } /// Parses the following grammar: From 10270bcd30d1d85a003412e597e367f2e7c89942 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:55:41 +0100 Subject: [PATCH 10/38] Fuse associated type parsing. --- src/librustc_parse/parser/item.rs | 33 ++++--------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d07fe358272c6..3fc4cafc0da5b 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -698,7 +698,7 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { - self.parse_impl_assoc_ty()? + self.parse_assoc_ty()? } else if self.is_const_item() { self.parse_assoc_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? { @@ -750,31 +750,6 @@ impl<'a> Parser<'a> { !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) } - /// Parses the following grammar: - /// - /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] - fn parse_impl_assoc_ty(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { - let ident = self.parse_ident()?; - let mut generics = self.parse_generics()?; - - // Parse optional colon and param bounds. - let bounds = if self.eat(&token::Colon) { - self.parse_generic_bounds(None)? - } else { - Vec::new() - }; - generics.where_clause = self.parse_where_clause()?; - - let default = if self.eat(&token::Eq) { - Some(self.parse_ty()?) - } else { - None - }; - self.expect_semi()?; - - Ok((ident, ImplItemKind::TyAlias(bounds, default), generics)) - } - /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. @@ -894,7 +869,7 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { - self.parse_trait_item_assoc_ty()? + self.parse_assoc_ty()? } else if self.is_const_item() { self.parse_assoc_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { @@ -937,7 +912,7 @@ impl<'a> Parser<'a> { /// Parses the following grammar: /// /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] - fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { + fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -956,7 +931,7 @@ impl<'a> Parser<'a> { }; self.expect_semi()?; - Ok((ident, TraitItemKind::TyAlias(bounds, default), generics)) + Ok((ident, AssocItemKind::TyAlias(bounds, default), generics)) } /// Parses a `UseTree`. From 7672bff3780ef0e7ba5313bf23644465644e19e6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 11:07:49 +0100 Subject: [PATCH 11/38] Unify associated function parsing. --- src/librustc_parse/parser/item.rs | 65 +++++++++++-------------------- src/libsyntax/ast.rs | 1 + 2 files changed, 24 insertions(+), 42 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3fc4cafc0da5b..32cc156783cc3 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -6,7 +6,7 @@ use crate::maybe_whole; use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey}; use rustc_error_codes::*; use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; -use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind}; +use syntax::ast::{ItemKind, ImplItem, TraitItem, TraitItemKind, UseTree, UseTreeKind}; use syntax::ast::{AssocItemKind}; use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit}; use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; @@ -705,7 +705,7 @@ impl<'a> Parser<'a> { // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default()) } else { - self.parse_impl_method(at_end, &mut attrs)? + self.parse_assoc_fn(at_end, &mut attrs, |_| true)? }; Ok(ImplItem { @@ -876,7 +876,11 @@ impl<'a> Parser<'a> { // trait item macro. (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default()) } else { - self.parse_trait_item_method(at_end, &mut attrs)? + // This is somewhat dubious; We don't want to allow + // param names to be left off if there is a definition... + // + // We don't allow param names to be left off in edition 2018. + self.parse_assoc_fn(at_end, &mut attrs, |t| t.span.rust_2018())? }; Ok(TraitItem { @@ -1823,48 +1827,40 @@ impl<'a> Parser<'a> { }) } - /// Parses a method or a macro invocation in a trait impl. - fn parse_impl_method( - &mut self, - at_end: &mut bool, - attrs: &mut Vec, - ) -> PResult<'a, (Ident, ImplItemKind, Generics)> { - let (ident, sig, generics) = self.parse_method_sig(|_| true)?; - let body = self.parse_trait_method_body(at_end, attrs)?; - Ok((ident, ast::ImplItemKind::Method(sig, body), generics)) - } - - fn parse_trait_item_method( + fn parse_assoc_fn( &mut self, at_end: &mut bool, attrs: &mut Vec, - ) -> PResult<'a, (Ident, TraitItemKind, Generics)> { - // This is somewhat dubious; We don't want to allow - // argument names to be left off if there is a definition... - // - // We don't allow argument names to be left off in edition 2018. - let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?; - let body = self.parse_trait_method_body(at_end, attrs)?; - Ok((ident, TraitItemKind::Method(sig, body), generics)) + is_name_required: fn(&token::Token) -> bool, + ) -> PResult<'a, (Ident, AssocItemKind, Generics)> { + let header = self.parse_fn_front_matter()?; + let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { + is_self_allowed: true, + allow_c_variadic: false, + is_name_required, + })?; + let sig = FnSig { header, decl }; + let body = self.parse_assoc_fn_body(at_end, attrs)?; + Ok((ident, AssocItemKind::Method(sig, body), generics)) } - /// Parse the "body" of a method in a trait item definition. + /// Parse the "body" of a method in an associated item definition. /// This can either be `;` when there's no body, /// or e.g. a block when the method is a provided one. - fn parse_trait_method_body( + fn parse_assoc_fn_body( &mut self, at_end: &mut bool, attrs: &mut Vec, ) -> PResult<'a, Option>> { Ok(match self.token.kind { token::Semi => { - debug!("parse_trait_method_body(): parsing required method"); + debug!("parse_assoc_fn_body(): parsing required method"); self.bump(); *at_end = true; None } token::OpenDelim(token::Brace) => { - debug!("parse_trait_method_body(): parsing provided method"); + debug!("parse_assoc_fn_body(): parsing provided method"); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(inner_attrs.iter().cloned()); @@ -1885,21 +1881,6 @@ impl<'a> Parser<'a> { }) } - /// Parse the "signature", including the identifier, parameters, and generics - /// of a method. The body is not parsed as that differs between `trait`s and `impl`s. - fn parse_method_sig( - &mut self, - is_name_required: fn(&token::Token) -> bool, - ) -> PResult<'a, (Ident, FnSig, Generics)> { - let header = self.parse_fn_front_matter()?; - let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { - is_self_allowed: true, - allow_c_variadic: false, - is_name_required, - })?; - Ok((ident, FnSig { header, decl }, generics)) - } - /// Parses all the "front matter" for a `fn` declaration, up to /// and including the `fn` keyword: /// diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index dd8a7fa8665c2..5866f9db078fd 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1640,6 +1640,7 @@ pub enum AssocItemKind { Const(P, Option>), /// An associated function. + /// FIXME(Centril): Rename to `Fn`. Method(FnSig, Option>), /// An associated type. From 63a9030e7b75312261733187f827df66db55cb1b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 11:30:04 +0100 Subject: [PATCH 12/38] Unify associated item parsing. An exception is `fn` params. --- src/librustc_parse/parser/item.rs | 70 ++++++--------------- src/test/ui/did_you_mean/issue-40006.rs | 4 +- src/test/ui/did_you_mean/issue-40006.stderr | 12 ++-- src/test/ui/parser/issue-21153.stderr | 2 +- 4 files changed, 29 insertions(+), 59 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 32cc156783cc3..3fbdbb4cb2240 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -6,8 +6,7 @@ use crate::maybe_whole; use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey}; use rustc_error_codes::*; use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; -use syntax::ast::{ItemKind, ImplItem, TraitItem, TraitItemKind, UseTree, UseTreeKind}; -use syntax::ast::{AssocItemKind}; +use syntax::ast::{AssocItem, AssocItemKind, ItemKind, UseTree, UseTreeKind}; use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit}; use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField}; @@ -649,7 +648,7 @@ impl<'a> Parser<'a> { Ok((Ident::invalid(), item_kind, Some(attrs))) } - fn parse_impl_body(&mut self) -> PResult<'a, (Vec, Vec)> { + fn parse_impl_body(&mut self) -> PResult<'a, (Vec, Vec)> { self.expect(&token::OpenDelim(token::Brace))?; let attrs = self.parse_inner_attributes()?; @@ -671,12 +670,12 @@ impl<'a> Parser<'a> { } /// Parses an impl item. - pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { + pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { maybe_whole!(self, NtImplItem, |x| x); let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_impl_item_(at_end, attrs); + let item = this.parse_assoc_item(at_end, attrs, |_| true); unclosed_delims.append(&mut this.unclosed_delims); item })?; @@ -689,38 +688,6 @@ impl<'a> Parser<'a> { Ok(item) } - fn parse_impl_item_( - &mut self, - at_end: &mut bool, - mut attrs: Vec, - ) -> PResult<'a, ImplItem> { - let lo = self.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - let defaultness = self.parse_defaultness(); - let (name, kind, generics) = if self.eat_keyword(kw::Type) { - self.parse_assoc_ty()? - } else if self.is_const_item() { - self.parse_assoc_const()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? { - // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! - (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default()) - } else { - self.parse_assoc_fn(at_end, &mut attrs, |_| true)? - }; - - Ok(ImplItem { - id: DUMMY_NODE_ID, - span: lo.to(self.prev_span), - ident: name, - attrs, - vis, - defaultness, - generics, - kind, - tokens: None, - }) - } - /// Parses defaultness (i.e., `default` or nothing). fn parse_defaultness(&mut self) -> Defaultness { // `pub` is included for better error messages @@ -843,12 +810,19 @@ impl<'a> Parser<'a> { } /// Parses the items in a trait declaration. - pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { + pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { maybe_whole!(self, NtTraitItem, |x| x); let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_trait_item_(at_end, attrs); + // This is somewhat dubious; We don't want to allow + // param names to be left off if there is a definition... + // + // We don't allow param names to be left off in edition 2018. + // + // FIXME(Centril): bake closure into param parsing. + // Also add semantic restrictions and add tests. + let item = this.parse_assoc_item(at_end, attrs, |t| t.span.rust_2018()); unclosed_delims.append(&mut this.unclosed_delims); item })?; @@ -860,11 +834,12 @@ impl<'a> Parser<'a> { Ok(item) } - fn parse_trait_item_( + fn parse_assoc_item( &mut self, at_end: &mut bool, mut attrs: Vec, - ) -> PResult<'a, TraitItem> { + is_name_required: fn(&token::Token) -> bool, + ) -> PResult<'a, AssocItem> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); @@ -872,18 +847,13 @@ impl<'a> Parser<'a> { self.parse_assoc_ty()? } else if self.is_const_item() { self.parse_assoc_const()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { - // trait item macro. - (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default()) + } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", Some(&vis), at_end)? { + (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default()) } else { - // This is somewhat dubious; We don't want to allow - // param names to be left off if there is a definition... - // - // We don't allow param names to be left off in edition 2018. - self.parse_assoc_fn(at_end, &mut attrs, |t| t.span.rust_2018())? + self.parse_assoc_fn(at_end, &mut attrs, is_name_required)? }; - Ok(TraitItem { + Ok(AssocItem { id: DUMMY_NODE_ID, span: lo.to(self.prev_span), ident: name, diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs index b3c1f60b7ebf6..ea21592997bfe 100644 --- a/src/test/ui/did_you_mean/issue-40006.rs +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -18,10 +18,10 @@ trait A { //~ ERROR missing trait B { fn xxx() { ### } //~ ERROR expected } -trait C { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration +trait C { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration L = M; } -trait D { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration +trait D { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration Z = { 2 + 3 }; } trait E { diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 30ae6ed4c6d49..d1e995013cb93 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,4 +1,4 @@ -error: missing `fn`, `type`, or `const` for impl-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:1:13 | LL | impl dyn A { @@ -6,7 +6,7 @@ LL | impl dyn A { LL | | Y | |____^ missing `fn`, `type`, or `const` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:7:10 | LL | trait X { @@ -14,7 +14,7 @@ LL | trait X { LL | | X() {} | |____^ missing `fn`, `type`, or `const` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:15:10 | LL | trait A { @@ -28,7 +28,7 @@ error: expected `[`, found `#` LL | fn xxx() { ### } | ^ expected `[` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:21:10 | LL | trait C { @@ -36,7 +36,7 @@ LL | trait C { LL | | L = M; | |____^ missing `fn`, `type`, or `const` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:24:10 | LL | trait D { @@ -50,7 +50,7 @@ error: expected one of `!` or `::`, found `(` LL | ::Y (); | ^ expected one of `!` or `::` -error: missing `fn`, `type`, or `const` for impl-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:32:8 | LL | pub hello_method(&self) { diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr index 70f55f0aeb9ff..6e20a9ce3c432 100644 --- a/src/test/ui/parser/issue-21153.stderr +++ b/src/test/ui/parser/issue-21153.stderr @@ -1,4 +1,4 @@ -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-21153.rs:1:29 | LL | trait MyTrait: Iterator { From fa828d7a0567cf833a8da9b10cc9936b3e9423dd Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 11:34:25 +0100 Subject: [PATCH 13/38] Relocate `is_const_item`. --- src/librustc_parse/parser/item.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3fbdbb4cb2240..dbc0163eef6a2 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -710,13 +710,6 @@ impl<'a> Parser<'a> { } } - /// Returns `true` if we are looking at `const ID` - /// (returns `false` for things like `const fn`, etc.). - fn is_const_item(&self) -> bool { - self.token.is_keyword(kw::Const) && - !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) - } - /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. @@ -866,6 +859,13 @@ impl<'a> Parser<'a> { }) } + /// Returns `true` if we are looking at `const ID` + /// (returns `false` for things like `const fn`, etc.). + fn is_const_item(&self) -> bool { + self.token.is_keyword(kw::Const) && + !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) + } + /// This parses the grammar: /// /// AssocConst = "const" Ident ":" Ty "=" Expr ";" From 404013e015d9a9f4835cda47e56aab5223f278ed Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 12:52:59 +0100 Subject: [PATCH 14/38] Leave a FIXME re. `allow_plus`. --- src/librustc_parse/parser/ty.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 84ffef68e9a66..33d7c878e888b 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -42,11 +42,12 @@ impl<'a> Parser<'a> { /// Parses an optional return type `[ -> TY ]` in a function declaration. pub(super) fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> { - if self.eat(&token::RArrow) { - Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?)) + Ok(if self.eat(&token::RArrow) { + // FIXME(Centril): Can we unconditionally `allow_plus`? + FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?) } else { - Ok(FunctionRetTy::Default(self.token.span.shrink_to_lo())) - } + FunctionRetTy::Default(self.token.span.shrink_to_lo()) + }) } pub(super) fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool, From 34d91709b672d91ea9623ae4bc2275e8b003fc2c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 16:00:08 +0100 Subject: [PATCH 15/38] parse: refactor fun ret ty & param ty --- src/librustc/hir/lowering.rs | 34 ++++------ src/librustc_interface/util.rs | 8 +-- src/librustc_parse/parser/expr.rs | 2 +- src/librustc_parse/parser/item.rs | 6 +- src/librustc_parse/parser/path.rs | 6 +- src/librustc_parse/parser/ty.rs | 26 ++++++-- src/librustc_passes/ast_validation.rs | 4 +- src/librustc_save_analysis/dump_visitor.rs | 9 ++- src/libsyntax/ast.rs | 4 +- src/libsyntax/mut_visit.rs | 8 ++- src/libsyntax/print/pprust.rs | 75 ++++++---------------- src/libsyntax/visit.rs | 2 +- 12 files changed, 77 insertions(+), 107 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 54ff1f56eec0d..e2c99f456e988 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2092,29 +2092,19 @@ impl<'a> LoweringContext<'a> { .iter() .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())) .collect(); + let output_ty = match output { + FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()), + FunctionRetTy::Default(_) => P(this.ty_tup(span, hir::HirVec::new())), + }; + let args = hir_vec![GenericArg::Type(this.ty_tup(span, inputs))]; + let binding = hir::TypeBinding { + hir_id: this.next_id(), + ident: Ident::with_dummy_span(FN_OUTPUT_NAME), + span: output_ty.span, + kind: hir::TypeBindingKind::Equality { ty: output_ty }, + }; ( - hir::GenericArgs { - args: hir_vec![GenericArg::Type(this.ty_tup(span, inputs))], - bindings: hir_vec![ - hir::TypeBinding { - hir_id: this.next_id(), - ident: Ident::with_dummy_span(FN_OUTPUT_NAME), - kind: hir::TypeBindingKind::Equality { - ty: output - .as_ref() - .map(|ty| this.lower_ty( - &ty, - ImplTraitContext::disallowed() - )) - .unwrap_or_else(|| - P(this.ty_tup(span, hir::HirVec::new())) - ), - }, - span: output.as_ref().map_or(span, |ty| ty.span), - } - ], - parenthesized: true, - }, + hir::GenericArgs { args, bindings: hir_vec![binding], parenthesized: true }, false, ) } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 8c225b83f40e8..ca7c4ba878638 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -712,8 +712,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { ret } - fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool { - if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output { + fn should_ignore_fn(ret_ty: &ast::FunctionRetTy) -> bool { + if let ast::FunctionRetTy::Ty(ref ty) = ret_ty { fn involves_impl_trait(ty: &ast::Ty) -> bool { match ty.kind { ast::TyKind::ImplTrait(..) => true, @@ -742,7 +742,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { }, Some(&ast::GenericArgs::Parenthesized(ref data)) => { any_involves_impl_trait(data.inputs.iter()) || - any_involves_impl_trait(data.output.iter()) + ReplaceBodyWithLoop::should_ignore_fn(&data.output) } } }), @@ -762,7 +762,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { fn is_sig_const(sig: &ast::FnSig) -> bool { sig.header.constness.node == ast::Constness::Const || - ReplaceBodyWithLoop::should_ignore_fn(&sig.decl) + ReplaceBodyWithLoop::should_ignore_fn(&sig.decl.output) } } diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3cd4988ce0be5..e4dff07e92cb8 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1381,7 +1381,7 @@ impl<'a> Parser<'a> { args } }; - let output = self.parse_ret_ty(true)?; + let output = self.parse_ret_ty(true, true)?; Ok(P(FnDecl { inputs: inputs_captures, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index dbc0163eef6a2..f391eda976ce4 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1900,7 +1900,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { Ok(P(FnDecl { inputs: self.parse_fn_params(cfg)?, - output: self.parse_ret_ty(ret_allow_plus)?, + output: self.parse_ret_ty(ret_allow_plus, true)?, })) } @@ -2002,12 +2002,12 @@ impl<'a> Parser<'a> { } self.eat_incorrect_doc_comment_for_param_type(); - (pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?) + (pat, self.parse_ty_for_param(cfg.allow_c_variadic)?) } else { debug!("parse_param_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); self.eat_incorrect_doc_comment_for_param_type(); - let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic); + let mut ty = self.parse_ty_for_param(cfg.allow_c_variadic); if ty.is_ok() && self.token != token::Comma && self.token != token::CloseDelim(token::Paren) { // This wasn't actually a type, but a pattern looking like a type, diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 5334fc485e7a6..aeba6dd2f67c5 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -182,11 +182,7 @@ impl<'a> Parser<'a> { // `(T, U) -> R` let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; let span = ident.span.to(self.prev_span); - let output = if self.eat(&token::RArrow) { - Some(self.parse_ty_common(false, false, false)?) - } else { - None - }; + let output = self.parse_ret_ty(false, false)?; ParenthesizedArgs { inputs, output, span }.into() }; diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 33d7c878e888b..1dffa6c94a898 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -30,6 +30,13 @@ impl<'a> Parser<'a> { self.parse_ty_common(true, true, false) } + /// Parse a type suitable for a function or function pointer parameter. + /// The difference from `parse_ty` is that this version allows `...` + /// (`CVarArgs`) at the top level of the the type. + pub(super) fn parse_ty_for_param(&mut self, allow_c_variadic: bool) -> PResult<'a, P> { + self.parse_ty_common(true, true, allow_c_variadic) + } + /// Parses a type in restricted contexts where `+` is not permitted. /// /// Example 1: `&'a TYPE` @@ -41,17 +48,26 @@ impl<'a> Parser<'a> { } /// Parses an optional return type `[ -> TY ]` in a function declaration. - pub(super) fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> { + pub(super) fn parse_ret_ty( + &mut self, + allow_plus: bool, + allow_qpath_recovery: bool, + ) -> PResult<'a, FunctionRetTy> { Ok(if self.eat(&token::RArrow) { // FIXME(Centril): Can we unconditionally `allow_plus`? - FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?) + FunctionRetTy::Ty(self.parse_ty_common(allow_plus, allow_qpath_recovery, false)?) } else { FunctionRetTy::Default(self.token.span.shrink_to_lo()) }) } - pub(super) fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool, - allow_c_variadic: bool) -> PResult<'a, P> { + fn parse_ty_common( + &mut self, + allow_plus: bool, + allow_qpath_recovery: bool, + // Is `...` (`CVarArgs`) legal in the immediate top level call? + allow_c_variadic: bool, + ) -> PResult<'a, P> { maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); maybe_whole!(self, NtTy, |x| x); @@ -198,6 +214,8 @@ impl<'a> Parser<'a> { self.eat(&token::DotDotDot); TyKind::CVarArgs } else { + // FIXME(Centril): Should we just allow `...` syntactically + // anywhere in a type and use semantic restrictions instead? return Err(struct_span_fatal!( self.sess.span_diagnostic, self.token.span, diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index f4b28077e9f02..8be97155d8c61 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -674,10 +674,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } GenericArgs::Parenthesized(ref data) => { walk_list!(self, visit_ty, &data.inputs); - if let Some(ref type_) = data.output { + if let FunctionRetTy::Ty(ty) = &data.output { // `-> Foo` syntax is essentially an associated type binding, // so it is also allowed to contain nested `impl Trait`. - self.with_impl_trait(None, |this| this.visit_ty(type_)); + self.with_impl_trait(None, |this| this.visit_ty(ty)); } } } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index d63a9df8d9bc4..cc0f3c512f53e 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -811,9 +811,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { match **generic_args { ast::GenericArgs::AngleBracketed(ref data) => { for arg in &data.args { - match arg { - ast::GenericArg::Type(ty) => self.visit_ty(ty), - _ => {} + if let ast::GenericArg::Type(ty) = arg { + self.visit_ty(ty); } } } @@ -821,8 +820,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { for t in &data.inputs { self.visit_ty(t); } - if let Some(ref t) = data.output { - self.visit_ty(t); + if let ast::FunctionRetTy::Ty(ty) = &data.output { + self.visit_ty(ty); } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5866f9db078fd..d90d74d7a262c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -254,7 +254,7 @@ pub struct ParenthesizedArgs { pub inputs: Vec>, /// `C` - pub output: Option>, + pub output: FunctionRetTy, } impl ParenthesizedArgs { @@ -2185,7 +2185,7 @@ impl fmt::Debug for ImplPolarity { } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum FunctionRetTy { +pub enum FunctionRetTy { // FIXME(Centril): Rename to `FnRetTy` and in HIR also. /// Returns type is not specified. /// /// Functions default to `()` and closures default to inference. diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index bb0462c19cdff..97a85b0fe7e35 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -553,7 +553,7 @@ pub fn noop_visit_parenthesized_parameter_data(args: &mut Parenth vis: &mut T) { let ParenthesizedArgs { inputs, output, span } = args; visit_vec(inputs, |input| vis.visit_ty(input)); - visit_opt(output, |output| vis.visit_ty(output)); + noop_visit_fn_ret_ty(output, vis); vis.visit_span(span); } @@ -742,7 +742,11 @@ pub fn noop_visit_asyncness(asyncness: &mut IsAsync, vis: &mut T) pub fn noop_visit_fn_decl(decl: &mut P, vis: &mut T) { let FnDecl { inputs, output } = decl.deref_mut(); inputs.flat_map_in_place(|param| vis.flat_map_param(param)); - match output { + noop_visit_fn_ret_ty(output, vis); +} + +pub fn noop_visit_fn_ret_ty(fn_ret_ty: &mut FunctionRetTy, vis: &mut T) { + match fn_ret_ty { FunctionRetTy::Default(span) => vis.visit_span(span), FunctionRetTy::Ty(ty) => vis.visit_ty(ty), } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 03e394b8c7e9c..a141d4d71bbda 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -887,17 +887,9 @@ impl<'a> PrintState<'a> for State<'a> { ast::GenericArgs::Parenthesized(ref data) => { self.s.word("("); - self.commasep( - Inconsistent, - &data.inputs, - |s, ty| s.print_type(ty)); + self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty)); self.s.word(")"); - - if let Some(ref ty) = data.output { - self.space_if_not_bol(); - self.word_space("->"); - self.print_type(ty); - } + self.print_fn_ret_ty(&data.output); } } } @@ -1579,6 +1571,7 @@ impl<'a> State<'a> { self.ann.post(self, AnnNode::SubItem(ti.id)) } + // FIXME(Centril): merge with function above. crate fn print_impl_item(&mut self, ii: &ast::ImplItem) { self.ann.pre(self, AnnNode::SubItem(ii.id)); self.hardbreak_if_not_bol(); @@ -2104,7 +2097,7 @@ impl<'a> State<'a> { self.print_asyncness(asyncness); self.print_capture_clause(capture_clause); - self.print_fn_block_params(decl); + self.print_fn_params_and_ret(decl, true); self.s.space(); self.print_expr(body); self.end(); // need to close a box @@ -2535,36 +2528,16 @@ impl<'a> State<'a> { self.print_ident(name); } self.print_generic_params(&generics.params); - self.print_fn_params_and_ret(decl); + self.print_fn_params_and_ret(decl, false); self.print_where_clause(&generics.where_clause) } - crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl) { - self.popen(); - self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, false)); - self.pclose(); - - self.print_fn_output(decl) - } - - crate fn print_fn_block_params(&mut self, decl: &ast::FnDecl) { - self.s.word("|"); - self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, true)); - self.s.word("|"); - - if let ast::FunctionRetTy::Default(..) = decl.output { - return; - } - - self.space_if_not_bol(); - self.word_space("->"); - match decl.output { - ast::FunctionRetTy::Ty(ref ty) => { - self.print_type(ty); - self.maybe_print_comment(ty.span.lo()) - } - ast::FunctionRetTy::Default(..) => unreachable!(), - } + crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) { + let (open, close) = if is_closure { ("|", "|") } else { ("(", ")") }; + self.word(open); + self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, is_closure)); + self.word(close); + self.print_fn_ret_ty(&decl.output) } crate fn print_movability(&mut self, movability: ast::Movability) { @@ -2786,24 +2759,14 @@ impl<'a> State<'a> { self.end(); } - crate fn print_fn_output(&mut self, decl: &ast::FnDecl) { - if let ast::FunctionRetTy::Default(..) = decl.output { - return; - } - - self.space_if_not_bol(); - self.ibox(INDENT_UNIT); - self.word_space("->"); - match decl.output { - ast::FunctionRetTy::Default(..) => unreachable!(), - ast::FunctionRetTy::Ty(ref ty) => - self.print_type(ty), - } - self.end(); - - match decl.output { - ast::FunctionRetTy::Ty(ref output) => self.maybe_print_comment(output.span.lo()), - _ => {} + crate fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FunctionRetTy) { + if let ast::FunctionRetTy::Ty(ty) = fn_ret_ty { + self.space_if_not_bol(); + self.ibox(INDENT_UNIT); + self.word_space("->"); + self.print_type(ty); + self.end(); + self.maybe_print_comment(ty.span.lo()); } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 7cc1a769e52bf..74df808b37e36 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -420,7 +420,7 @@ pub fn walk_generic_args<'a, V>(visitor: &mut V, } GenericArgs::Parenthesized(ref data) => { walk_list!(visitor, visit_ty, &data.inputs); - walk_list!(visitor, visit_ty, &data.output); + walk_fn_ret_ty(visitor, &data.output); } } } From 9193d7a07e3c70f5f41c8a92aa34c120c9fdba0d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 16:15:10 +0100 Subject: [PATCH 16/38] Unify associated item pretty printing. --- src/libsyntax/print/pprust.rs | 96 ++++++++--------------------------- 1 file changed, 21 insertions(+), 75 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a141d4d71bbda..9e4615f60c03c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -335,8 +335,8 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String { token::NtLifetime(e) => e.to_string(), token::NtLiteral(ref e) => expr_to_string(e), token::NtTT(ref tree) => tt_to_string(tree.clone()), - token::NtImplItem(ref e) => impl_item_to_string(e), - token::NtTraitItem(ref e) => trait_item_to_string(e), + // FIXME(Centril): merge these variants. + token::NtImplItem(ref e) | token::NtTraitItem(ref e) => assoc_item_to_string(e), token::NtVis(ref e) => vis_to_string(e), token::NtForeignItem(ref e) => foreign_item_to_string(e), } @@ -374,12 +374,8 @@ pub fn item_to_string(i: &ast::Item) -> String { to_string(|s| s.print_item(i)) } -fn impl_item_to_string(i: &ast::ImplItem) -> String { - to_string(|s| s.print_impl_item(i)) -} - -fn trait_item_to_string(i: &ast::TraitItem) -> String { - to_string(|s| s.print_trait_item(i)) +fn assoc_item_to_string(i: &ast::AssocItem) -> String { + to_string(|s| s.print_assoc_item(i)) } pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String { @@ -1301,7 +1297,7 @@ impl<'a> State<'a> { self.bopen(); self.print_inner_attributes(&item.attrs); for impl_item in impl_items { - self.print_impl_item(impl_item); + self.print_assoc_item(impl_item); } self.bclose(item.span); } @@ -1328,7 +1324,7 @@ impl<'a> State<'a> { self.s.word(" "); self.bopen(); for trait_item in trait_items { - self.print_trait_item(trait_item); + self.print_assoc_item(trait_item); } self.bclose(item.span); } @@ -1522,89 +1518,39 @@ impl<'a> State<'a> { } } - crate fn print_method_sig(&mut self, - ident: ast::Ident, - generics: &ast::Generics, - m: &ast::FnSig, - vis: &ast::Visibility) - { - self.print_fn(&m.decl, - m.header, - Some(ident), - &generics, - vis) - } - - crate fn print_trait_item(&mut self, ti: &ast::TraitItem) - { - self.ann.pre(self, AnnNode::SubItem(ti.id)); + crate fn print_assoc_item(&mut self, item: &ast::AssocItem) { + self.ann.pre(self, AnnNode::SubItem(item.id)); self.hardbreak_if_not_bol(); - self.maybe_print_comment(ti.span.lo()); - self.print_outer_attributes(&ti.attrs); - self.print_defaultness(ti.defaultness); - match ti.kind { - ast::TraitItemKind::Const(ref ty, ref default) => { - self.print_associated_const(ti.ident, ty, default.as_deref(), &ti.vis); - } - ast::TraitItemKind::Method(ref sig, ref body) => { - if body.is_some() { - self.head(""); - } - self.print_method_sig(ti.ident, &ti.generics, sig, &ti.vis); - if let Some(ref body) = *body { - self.nbsp(); - self.print_block_with_attrs(body, &ti.attrs); - } else { - self.s.word(";"); - } - } - ast::TraitItemKind::TyAlias(ref bounds, ref default) => { - self.print_associated_type(ti.ident, bounds, default.as_deref()); - } - ast::TraitItemKind::Macro(ref mac) => { - self.print_mac(mac); - if mac.args.need_semicolon() { - self.s.word(";"); - } + self.maybe_print_comment(item.span.lo()); + self.print_outer_attributes(&item.attrs); + self.print_defaultness(item.defaultness); + match &item.kind { + ast::AssocItemKind::Const(ty, expr) => { + self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis); } - } - self.ann.post(self, AnnNode::SubItem(ti.id)) - } - - // FIXME(Centril): merge with function above. - crate fn print_impl_item(&mut self, ii: &ast::ImplItem) { - self.ann.pre(self, AnnNode::SubItem(ii.id)); - self.hardbreak_if_not_bol(); - self.maybe_print_comment(ii.span.lo()); - self.print_outer_attributes(&ii.attrs); - self.print_defaultness(ii.defaultness); - match ii.kind { - ast::ImplItemKind::Const(ref ty, ref expr) => { - self.print_associated_const(ii.ident, ty, expr.as_deref(), &ii.vis); - } - ast::ImplItemKind::Method(ref sig, ref body) => { + ast::AssocItemKind::Method(sig, body) => { if body.is_some() { self.head(""); } - self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis); + self.print_fn(&sig.decl, sig.header, Some(item.ident), &item.generics, &item.vis); if let Some(body) = body { self.nbsp(); - self.print_block_with_attrs(body, &ii.attrs); + self.print_block_with_attrs(body, &item.attrs); } else { self.s.word(";"); } } - ast::ImplItemKind::TyAlias(ref bounds, ref ty) => { - self.print_associated_type(ii.ident, bounds, ty.as_deref()); + ast::AssocItemKind::TyAlias(bounds, ty) => { + self.print_associated_type(item.ident, bounds, ty.as_deref()); } - ast::ImplItemKind::Macro(ref mac) => { + ast::AssocItemKind::Macro(mac) => { self.print_mac(mac); if mac.args.need_semicolon() { self.s.word(";"); } } } - self.ann.post(self, AnnNode::SubItem(ii.id)) + self.ann.post(self, AnnNode::SubItem(item.id)) } crate fn print_stmt(&mut self, st: &ast::Stmt) { From 76576d401c3fc33bab78cf022d0c4901d9b89548 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 16:58:37 +0100 Subject: [PATCH 17/38] Unify associated item mut visitors. --- src/librustc_interface/util.rs | 4 +-- src/librustc_parse/config.rs | 8 ++--- src/libsyntax/mut_visit.rs | 54 ++++++---------------------- src/libsyntax_expand/expand.rs | 16 ++++----- src/libsyntax_expand/placeholders.rs | 12 +++---- 5 files changed, 31 insertions(+), 63 deletions(-) diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index ca7c4ba878638..026cb6eab1c7d 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -782,7 +782,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { ast::TraitItemKind::Method(ref sig, _) => Self::is_sig_const(sig), _ => false, }; - self.run(is_const, |s| noop_flat_map_trait_item(i, s)) + self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) } fn flat_map_impl_item(&mut self, i: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { @@ -791,7 +791,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { ast::ImplItemKind::Method(ref sig, _) => Self::is_sig_const(sig), _ => false, }; - self.run(is_const, |s| noop_flat_map_impl_item(i, s)) + self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) } fn visit_anon_const(&mut self, c: &mut ast::AnonConst) { diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 1e9203f377f38..38ae7050abe48 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -344,12 +344,12 @@ impl<'a> MutVisitor for StripUnconfigured<'a> { noop_flat_map_item(configure!(self, item), self) } - fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { - noop_flat_map_impl_item(configure!(self, item), self) + fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { + noop_flat_map_assoc_item(configure!(self, item), self) } - fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { - noop_flat_map_trait_item(configure!(self, item), self) + fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { + noop_flat_map_assoc_item(configure!(self, item), self) } fn visit_mac(&mut self, _mac: &mut ast::Mac) { diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 97a85b0fe7e35..18d42f9dd668c 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -103,12 +103,12 @@ pub trait MutVisitor: Sized { noop_visit_item_kind(i, self); } - fn flat_map_trait_item(&mut self, i: TraitItem) -> SmallVec<[TraitItem; 1]> { - noop_flat_map_trait_item(i, self) + fn flat_map_trait_item(&mut self, i: AssocItem) -> SmallVec<[AssocItem; 1]> { + noop_flat_map_assoc_item(i, self) } - fn flat_map_impl_item(&mut self, i: ImplItem) -> SmallVec<[ImplItem; 1]> { - noop_flat_map_impl_item(i, self) + fn flat_map_impl_item(&mut self, i: AssocItem) -> SmallVec<[AssocItem; 1]> { + noop_flat_map_assoc_item(i, self) } fn visit_fn_decl(&mut self, d: &mut P) { @@ -940,42 +940,10 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { } } -pub fn noop_flat_map_trait_item(mut item: TraitItem, visitor: &mut T) - -> SmallVec<[TraitItem; 1]> +pub fn noop_flat_map_assoc_item(mut item: AssocItem, visitor: &mut T) + -> SmallVec<[AssocItem; 1]> { - let TraitItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } = - &mut item; - visitor.visit_id(id); - visitor.visit_ident(ident); - visitor.visit_vis(vis); - visit_attrs(attrs, visitor); - visitor.visit_generics(generics); - match kind { - TraitItemKind::Const(ty, default) => { - visitor.visit_ty(ty); - visit_opt(default, |default| visitor.visit_expr(default)); - } - TraitItemKind::Method(sig, body) => { - visit_fn_sig(sig, visitor); - visit_opt(body, |body| visitor.visit_block(body)); - } - TraitItemKind::TyAlias(bounds, default) => { - visit_bounds(bounds, visitor); - visit_opt(default, |default| visitor.visit_ty(default)); - } - TraitItemKind::Macro(mac) => { - visitor.visit_mac(mac); - } - } - visitor.visit_span(span); - - smallvec![item] -} - -pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut T) - -> SmallVec<[ImplItem; 1]> -{ - let ImplItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } = + let AssocItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } = &mut item; visitor.visit_id(id); visitor.visit_ident(ident); @@ -983,19 +951,19 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut visit_attrs(attrs, visitor); visitor.visit_generics(generics); match kind { - ImplItemKind::Const(ty, expr) => { + AssocItemKind::Const(ty, expr) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } - ImplItemKind::Method(sig, body) => { + AssocItemKind::Method(sig, body) => { visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - ImplItemKind::TyAlias(bounds, ty) => { + AssocItemKind::TyAlias(bounds, ty) => { visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); } - ImplItemKind::Macro(mac) => visitor.visit_mac(mac), + AssocItemKind::Macro(mac) => visitor.visit_mac(mac), } visitor.visit_span(span); diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs index 9bfedb3b6174e..2eae6d494d07a 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -1317,7 +1317,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { + fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { let mut item = configure!(self, item); let (attr, traits, after_derive) = self.classify_item(&mut item); @@ -1327,16 +1327,16 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } match item.kind { - ast::TraitItemKind::Macro(mac) => { - let ast::TraitItem { attrs, span, .. } = item; + ast::AssocItemKind::Macro(mac) => { + let ast::AssocItem { attrs, span, .. } = item; self.check_attributes(&attrs); self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items() } - _ => noop_flat_map_trait_item(item, self), + _ => noop_flat_map_assoc_item(item, self), } } - fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { + fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { let mut item = configure!(self, item); let (attr, traits, after_derive) = self.classify_item(&mut item); @@ -1346,12 +1346,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } match item.kind { - ast::ImplItemKind::Macro(mac) => { - let ast::ImplItem { attrs, span, .. } = item; + ast::AssocItemKind::Macro(mac) => { + let ast::AssocItem { attrs, span, .. } = item; self.check_attributes(&attrs); self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items() } - _ => noop_flat_map_impl_item(item, self), + _ => noop_flat_map_assoc_item(item, self), } } diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs index 6057be9826a51..18acbf2cc13d9 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -253,17 +253,17 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { noop_flat_map_item(item, self) } - fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { + fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { match item.kind { - ast::TraitItemKind::Macro(_) => self.remove(item.id).make_trait_items(), - _ => noop_flat_map_trait_item(item, self), + ast::AssocItemKind::Macro(_) => self.remove(item.id).make_trait_items(), + _ => noop_flat_map_assoc_item(item, self), } } - fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { + fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { match item.kind { - ast::ImplItemKind::Macro(_) => self.remove(item.id).make_impl_items(), - _ => noop_flat_map_impl_item(item, self), + ast::AssocItemKind::Macro(_) => self.remove(item.id).make_impl_items(), + _ => noop_flat_map_assoc_item(item, self), } } From c6c17e3e00273395869f7025f02c4be99c9f99b4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 17:00:20 +0100 Subject: [PATCH 18/38] Simplify `nt_to_tokenstream`. --- src/librustc_parse/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index faff386e92318..58c3652438057 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -305,10 +305,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke Nonterminal::NtItem(ref item) => { prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) } - Nonterminal::NtTraitItem(ref item) => { - prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) - } - Nonterminal::NtImplItem(ref item) => { + Nonterminal::NtTraitItem(ref item) | Nonterminal::NtImplItem(ref item) => { prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) } Nonterminal::NtIdent(ident, is_raw) => { From 0d8a9d74e3bbeed1ad787e1b563e6884496728b2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 17:11:07 +0100 Subject: [PATCH 19/38] Unify associated item visitor. --- src/librustc/hir/lowering.rs | 6 +-- src/librustc/hir/lowering/item.rs | 4 +- src/librustc/lint/context.rs | 4 +- src/librustc_passes/ast_validation.rs | 14 ++--- src/librustc_passes/hir_stats.rs | 4 +- src/librustc_resolve/build_reduced_graph.rs | 4 +- src/librustc_resolve/def_collector.rs | 4 +- src/librustc_resolve/late.rs | 8 +-- src/libsyntax/feature_gate/check.rs | 4 +- src/libsyntax/util/node_count.rs | 4 +- src/libsyntax/visit.rs | 58 ++++++--------------- 11 files changed, 43 insertions(+), 71 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e2c99f456e988..1ee02dcf0c189 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -484,11 +484,11 @@ impl<'a> LoweringContext<'a> { TraitItemKind::Method(_, None) => { // Ignore patterns in trait methods without bodies self.with_hir_id_owner(None, |this| { - visit::walk_trait_item(this, item) + visit::walk_assoc_item(this, item) }); } _ => self.with_hir_id_owner(Some(item.id), |this| { - visit::walk_trait_item(this, item); + visit::walk_assoc_item(this, item); }) } } @@ -496,7 +496,7 @@ impl<'a> LoweringContext<'a> { fn visit_impl_item(&mut self, item: &'tcx ImplItem) { self.lctx.allocate_hir_id_counter(item.id); self.with_hir_id_owner(Some(item.id), |this| { - visit::walk_impl_item(this, item); + visit::walk_assoc_item(this, item); }); } diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index f77523e638275..c3d2ed6b39cd2 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -94,7 +94,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id); }); - visit::walk_trait_item(self, item); + visit::walk_assoc_item(self, item); } fn visit_impl_item(&mut self, item: &'tcx ImplItem) { @@ -104,7 +104,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { lctx.impl_items.insert(id, hir_item); lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id); }); - visit::walk_impl_item(self, item); + visit::walk_assoc_item(self, item); } } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7f72154e42c61..e0ec9e62645d4 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1252,7 +1252,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> fn visit_trait_item(&mut self, trait_item: &'a ast::TraitItem) { self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| { run_early_pass!(cx, check_trait_item, trait_item); - ast_visit::walk_trait_item(cx, trait_item); + ast_visit::walk_assoc_item(cx, trait_item); run_early_pass!(cx, check_trait_item_post, trait_item); }); } @@ -1260,7 +1260,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> fn visit_impl_item(&mut self, impl_item: &'a ast::ImplItem) { self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| { run_early_pass!(cx, check_impl_item, impl_item); - ast_visit::walk_impl_item(cx, impl_item); + ast_visit::walk_assoc_item(cx, impl_item); run_early_pass!(cx, check_impl_item_post, impl_item); }); } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 8be97155d8c61..34534d6cca510 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -772,28 +772,28 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |this| visit::walk_enum_def(this, enum_definition, generics, item_id)) } - fn visit_impl_item(&mut self, ii: &'a ImplItem) { + fn visit_impl_item(&mut self, ii: &'a AssocItem) { match &ii.kind { - ImplItemKind::Const(_, body) => { + AssocItemKind::Const(_, body) => { self.check_impl_item_provided(ii.span, body, "constant", " = ;"); } - ImplItemKind::Method(sig, body) => { + AssocItemKind::Method(sig, body) => { self.check_impl_item_provided(ii.span, body, "function", " { }"); self.check_fn_decl(&sig.decl); } - ImplItemKind::TyAlias(bounds, body) => { + AssocItemKind::TyAlias(bounds, body) => { self.check_impl_item_provided(ii.span, body, "type", " = ;"); self.check_impl_assoc_type_no_bounds(bounds); } _ => {} } - visit::walk_impl_item(self, ii); + visit::walk_assoc_item(self, ii); } - fn visit_trait_item(&mut self, ti: &'a TraitItem) { + fn visit_trait_item(&mut self, ti: &'a AssocItem) { self.invalid_visibility(&ti.vis, None); self.check_defaultness(ti.span, ti.defaultness); - visit::walk_trait_item(self, ti); + visit::walk_assoc_item(self, ti); } } diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index a5924efefc2af..071ed0db87020 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -316,12 +316,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) { self.record("TraitItem", Id::None, ti); - ast_visit::walk_trait_item(self, ti) + ast_visit::walk_assoc_item(self, ti) } fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) { self.record("ImplItem", Id::None, ii); - ast_visit::walk_impl_item(self, ii) + ast_visit::walk_assoc_item(self, ii) } fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound) { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index d2d5a33ec7aa9..abed4b326a5f7 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1190,7 +1190,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let expansion = self.parent_scope.expansion; self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion)); - visit::walk_trait_item(self, item); + visit::walk_assoc_item(self, item); } fn visit_impl_item(&mut self, item: &'b ast::ImplItem) { @@ -1198,7 +1198,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { self.visit_invoc(item.id); } else { self.resolve_visibility(&item.vis); - visit::walk_impl_item(self, item); + visit::walk_assoc_item(self, item); } } diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 471e2634b8acf..248027a91ab3d 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -223,7 +223,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { }; let def = self.create_def(ti.id, def_data, ti.span); - self.with_parent(def, |this| visit::walk_trait_item(this, ti)); + self.with_parent(def, |this| visit::walk_assoc_item(this, ti)); } fn visit_impl_item(&mut self, ii: &'a ImplItem) { @@ -249,7 +249,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { }; let def = self.create_def(ii.id, def_data, ii.span); - self.with_parent(def, |this| visit::walk_impl_item(this, ii)); + self.with_parent(def, |this| visit::walk_assoc_item(this, ii)); } fn visit_pat(&mut self, pat: &'a Pat) { diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 33e24c8cfd4a7..682ddc421c287 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -819,10 +819,10 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } } TraitItemKind::Method(_, _) => { - visit::walk_trait_item(this, trait_item) + visit::walk_assoc_item(this, trait_item) } TraitItemKind::TyAlias(..) => { - visit::walk_trait_item(this, trait_item) + visit::walk_assoc_item(this, trait_item) } TraitItemKind::Macro(_) => { panic!("unexpanded macro in resolve!") @@ -1106,7 +1106,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ); this.with_constant_rib(|this| { - visit::walk_impl_item(this, impl_item) + visit::walk_assoc_item(this, impl_item) }); } ImplItemKind::Method(..) => { @@ -1117,7 +1117,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { impl_item.span, |n, s| MethodNotMemberOfTrait(n, s)); - visit::walk_impl_item(this, impl_item); + visit::walk_assoc_item(this, impl_item); } ImplItemKind::TyAlias(_, Some(ref ty)) => { // If this is a trait impl, ensure the type diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index f786de6401a6e..226719c746061 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -595,7 +595,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } _ => {} } - visit::walk_trait_item(self, ti) + visit::walk_assoc_item(self, ti) } fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) { @@ -620,7 +620,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } _ => {} } - visit::walk_impl_item(self, ii) + visit::walk_assoc_item(self, ii) } fn visit_vis(&mut self, vis: &'a ast::Visibility) { diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index a64fec7096132..14ca7a7eff30d 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -75,11 +75,11 @@ impl<'ast> Visitor<'ast> for NodeCounter { } fn visit_trait_item(&mut self, ti: &TraitItem) { self.count += 1; - walk_trait_item(self, ti) + walk_assoc_item(self, ti) } fn visit_impl_item(&mut self, ii: &ImplItem) { self.count += 1; - walk_impl_item(self, ii) + walk_assoc_item(self, ii) } fn visit_trait_ref(&mut self, t: &TraitRef) { self.count += 1; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 74df808b37e36..8fe8e136c10b1 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -83,8 +83,8 @@ pub trait Visitor<'ast>: Sized { fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) { walk_fn(self, fk, fd, s) } - fn visit_trait_item(&mut self, ti: &'ast TraitItem) { walk_trait_item(self, ti) } - fn visit_impl_item(&mut self, ii: &'ast ImplItem) { walk_impl_item(self, ii) } + fn visit_trait_item(&mut self, i: &'ast AssocItem) { walk_assoc_item(self, i) } + fn visit_impl_item(&mut self, i: &'ast AssocItem) { walk_assoc_item(self, i) } fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) } fn visit_param_bound(&mut self, bounds: &'ast GenericBound) { walk_param_bound(self, bounds) @@ -581,57 +581,29 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl } } -pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) { - visitor.visit_vis(&trait_item.vis); - visitor.visit_ident(trait_item.ident); - walk_list!(visitor, visit_attribute, &trait_item.attrs); - visitor.visit_generics(&trait_item.generics); - match trait_item.kind { - TraitItemKind::Const(ref ty, ref default) => { - visitor.visit_ty(ty); - walk_list!(visitor, visit_expr, default); - } - TraitItemKind::Method(ref sig, None) => { - visitor.visit_fn_header(&sig.header); - walk_fn_decl(visitor, &sig.decl); - } - TraitItemKind::Method(ref sig, Some(ref body)) => { - visitor.visit_fn(FnKind::Method(trait_item.ident, sig, &trait_item.vis, body), - &sig.decl, trait_item.span, trait_item.id); - } - TraitItemKind::TyAlias(ref bounds, ref default) => { - walk_list!(visitor, visit_param_bound, bounds); - walk_list!(visitor, visit_ty, default); - } - TraitItemKind::Macro(ref mac) => { - visitor.visit_mac(mac); - } - } -} - -pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplItem) { - visitor.visit_vis(&impl_item.vis); - visitor.visit_ident(impl_item.ident); - walk_list!(visitor, visit_attribute, &impl_item.attrs); - visitor.visit_generics(&impl_item.generics); - match impl_item.kind { - ImplItemKind::Const(ref ty, ref expr) => { +pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) { + visitor.visit_vis(&item.vis); + visitor.visit_ident(item.ident); + walk_list!(visitor, visit_attribute, &item.attrs); + visitor.visit_generics(&item.generics); + match item.kind { + AssocItemKind::Const(ref ty, ref expr) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - ImplItemKind::Method(ref sig, None) => { + AssocItemKind::Method(ref sig, None) => { visitor.visit_fn_header(&sig.header); walk_fn_decl(visitor, &sig.decl); } - ImplItemKind::Method(ref sig, Some(ref body)) => { - visitor.visit_fn(FnKind::Method(impl_item.ident, sig, &impl_item.vis, body), - &sig.decl, impl_item.span, impl_item.id); + AssocItemKind::Method(ref sig, Some(ref body)) => { + visitor.visit_fn(FnKind::Method(item.ident, sig, &item.vis, body), + &sig.decl, item.span, item.id); } - ImplItemKind::TyAlias(ref bounds, ref ty) => { + AssocItemKind::TyAlias(ref bounds, ref ty) => { walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); } - ImplItemKind::Macro(ref mac) => { + AssocItemKind::Macro(ref mac) => { visitor.visit_mac(mac); } } From 51ccdebe0b07f38e7e371a80424285539811c048 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 17:29:13 +0100 Subject: [PATCH 20/38] Unify associated item parsing more. --- src/librustc_parse/parser/item.rs | 49 +++++++++++++------------------ 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index f391eda976ce4..0126297a3586e 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -669,25 +669,6 @@ impl<'a> Parser<'a> { Ok((impl_items, attrs)) } - /// Parses an impl item. - pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { - maybe_whole!(self, NtImplItem, |x| x); - let attrs = self.parse_outer_attributes()?; - let mut unclosed_delims = vec![]; - let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_assoc_item(at_end, attrs, |_| true); - unclosed_delims.append(&mut this.unclosed_delims); - item - })?; - self.unclosed_delims.append(&mut unclosed_delims); - - // See `parse_item` for why this clause is here. - if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - item.tokens = Some(tokens); - } - Ok(item) - } - /// Parses defaultness (i.e., `default` or nothing). fn parse_defaultness(&mut self) -> Defaultness { // `pub` is included for better error messages @@ -802,20 +783,30 @@ impl<'a> Parser<'a> { } } - /// Parses the items in a trait declaration. + pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { + maybe_whole!(self, NtImplItem, |x| x); + self.parse_assoc_item(at_end, |_| true) + } + pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { maybe_whole!(self, NtTraitItem, |x| x); + // This is somewhat dubious; We don't want to allow + // param names to be left off if there is a definition... + // + // We don't allow param names to be left off in edition 2018. + self.parse_assoc_item(at_end, |t| t.span.rust_2018()) + } + + /// Parses associated items. + fn parse_assoc_item( + &mut self, + at_end: &mut bool, + is_name_required: fn(&token::Token) -> bool, + ) -> PResult<'a, AssocItem> { let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - // This is somewhat dubious; We don't want to allow - // param names to be left off if there is a definition... - // - // We don't allow param names to be left off in edition 2018. - // - // FIXME(Centril): bake closure into param parsing. - // Also add semantic restrictions and add tests. - let item = this.parse_assoc_item(at_end, attrs, |t| t.span.rust_2018()); + let item = this.parse_assoc_item_(at_end, attrs, is_name_required); unclosed_delims.append(&mut this.unclosed_delims); item })?; @@ -827,7 +818,7 @@ impl<'a> Parser<'a> { Ok(item) } - fn parse_assoc_item( + fn parse_assoc_item_( &mut self, at_end: &mut bool, mut attrs: Vec, From b499a88dfc484f077ec7264bd7fae7d7c60d9fb8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 02:03:31 +0100 Subject: [PATCH 21/38] Unify assoc item visitors more. --- src/librustc/hir/lowering.rs | 6 ++-- src/librustc/lint/context.rs | 4 +-- src/librustc_passes/ast_validation.rs | 4 +-- src/librustc_passes/hir_stats.rs | 4 +-- src/librustc_resolve/build_reduced_graph.rs | 4 +-- src/librustc_resolve/def_collector.rs | 4 +-- src/libsyntax/feature_gate/check.rs | 32 ++++++++----------- src/libsyntax/util/node_count.rs | 6 +--- src/libsyntax/visit.rs | 13 ++++++-- .../feature-gate-type_alias_impl_trait.stderr | 18 +++++------ ...ait-item-with-defaultness-fail-semantic.rs | 2 ++ ...item-with-defaultness-fail-semantic.stderr | 12 +++---- 12 files changed, 56 insertions(+), 53 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1ee02dcf0c189..e2c99f456e988 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -484,11 +484,11 @@ impl<'a> LoweringContext<'a> { TraitItemKind::Method(_, None) => { // Ignore patterns in trait methods without bodies self.with_hir_id_owner(None, |this| { - visit::walk_assoc_item(this, item) + visit::walk_trait_item(this, item) }); } _ => self.with_hir_id_owner(Some(item.id), |this| { - visit::walk_assoc_item(this, item); + visit::walk_trait_item(this, item); }) } } @@ -496,7 +496,7 @@ impl<'a> LoweringContext<'a> { fn visit_impl_item(&mut self, item: &'tcx ImplItem) { self.lctx.allocate_hir_id_counter(item.id); self.with_hir_id_owner(Some(item.id), |this| { - visit::walk_assoc_item(this, item); + visit::walk_impl_item(this, item); }); } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index e0ec9e62645d4..7f72154e42c61 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1252,7 +1252,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> fn visit_trait_item(&mut self, trait_item: &'a ast::TraitItem) { self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| { run_early_pass!(cx, check_trait_item, trait_item); - ast_visit::walk_assoc_item(cx, trait_item); + ast_visit::walk_trait_item(cx, trait_item); run_early_pass!(cx, check_trait_item_post, trait_item); }); } @@ -1260,7 +1260,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> fn visit_impl_item(&mut self, impl_item: &'a ast::ImplItem) { self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| { run_early_pass!(cx, check_impl_item, impl_item); - ast_visit::walk_assoc_item(cx, impl_item); + ast_visit::walk_impl_item(cx, impl_item); run_early_pass!(cx, check_impl_item_post, impl_item); }); } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 34534d6cca510..ad6c99494a60f 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -787,13 +787,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } _ => {} } - visit::walk_assoc_item(self, ii); + visit::walk_impl_item(self, ii); } fn visit_trait_item(&mut self, ti: &'a AssocItem) { self.invalid_visibility(&ti.vis, None); self.check_defaultness(ti.span, ti.defaultness); - visit::walk_assoc_item(self, ti); + visit::walk_trait_item(self, ti); } } diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 071ed0db87020..a5924efefc2af 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -316,12 +316,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) { self.record("TraitItem", Id::None, ti); - ast_visit::walk_assoc_item(self, ti) + ast_visit::walk_trait_item(self, ti) } fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) { self.record("ImplItem", Id::None, ii); - ast_visit::walk_assoc_item(self, ii) + ast_visit::walk_impl_item(self, ii) } fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound) { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index abed4b326a5f7..d2d5a33ec7aa9 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1190,7 +1190,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let expansion = self.parent_scope.expansion; self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion)); - visit::walk_assoc_item(self, item); + visit::walk_trait_item(self, item); } fn visit_impl_item(&mut self, item: &'b ast::ImplItem) { @@ -1198,7 +1198,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { self.visit_invoc(item.id); } else { self.resolve_visibility(&item.vis); - visit::walk_assoc_item(self, item); + visit::walk_impl_item(self, item); } } diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 248027a91ab3d..471e2634b8acf 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -223,7 +223,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { }; let def = self.create_def(ti.id, def_data, ti.span); - self.with_parent(def, |this| visit::walk_assoc_item(this, ti)); + self.with_parent(def, |this| visit::walk_trait_item(this, ti)); } fn visit_impl_item(&mut self, ii: &'a ImplItem) { @@ -249,7 +249,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { }; let def = self.create_def(ii.id, def_data, ii.span); - self.with_parent(def, |this| visit::walk_assoc_item(this, ii)); + self.with_parent(def, |this| visit::walk_impl_item(this, ii)); } fn visit_pat(&mut self, pat: &'a Pat) { diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 226719c746061..c27fcb6a68e0f 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -577,42 +577,38 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if block.is_none() { self.check_extern(sig.header.ext); } - if sig.decl.c_variadic() { - gate_feature_post!(&self, c_variadic, ti.span, - "C-variadic functions are unstable"); - } if sig.header.constness.node == ast::Constness::Const { gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); } } ast::TraitItemKind::TyAlias(_, ref default) => { - if let Some(ty) = default { - self.check_impl_trait(ty); - gate_feature_post!(&self, associated_type_defaults, ti.span, - "associated type defaults are unstable"); + if let Some(_) = default { + gate_feature_post!( + &self, associated_type_defaults, ti.span, + "associated type defaults are unstable" + ); } - self.check_gat(&ti.generics, ti.span); } _ => {} } - visit::walk_assoc_item(self, ti) + visit::walk_trait_item(self, ti) } - fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) { + fn visit_assoc_item(&mut self, ii: &'a ast::AssocItem) { if ii.defaultness == ast::Defaultness::Default { - gate_feature_post!(&self, specialization, - ii.span, - "specialization is unstable"); + gate_feature_post!(&self, specialization, ii.span, "specialization is unstable"); } match ii.kind { - ast::ImplItemKind::Method(ref sig, _) => { + ast::AssocItemKind::Method(ref sig, _) => { if sig.decl.c_variadic() { - gate_feature_post!(&self, c_variadic, ii.span, - "C-variadic functions are unstable"); + gate_feature_post!( + &self, c_variadic, ii.span, + "C-variadic functions are unstable" + ); } } - ast::ImplItemKind::TyAlias(_, ref ty) => { + ast::AssocItemKind::TyAlias(_, ref ty) => { if let Some(ty) = ty { self.check_impl_trait(ty); } diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index 14ca7a7eff30d..3db9955d304a3 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -73,14 +73,10 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_fn(self, fk, fd, s) } - fn visit_trait_item(&mut self, ti: &TraitItem) { + fn visit_assoc_item(&mut self, ti: &AssocItem) { self.count += 1; walk_assoc_item(self, ti) } - fn visit_impl_item(&mut self, ii: &ImplItem) { - self.count += 1; - walk_assoc_item(self, ii) - } fn visit_trait_ref(&mut self, t: &TraitRef) { self.count += 1; walk_trait_ref(self, t) diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 8fe8e136c10b1..e2c0ee6146741 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -83,8 +83,9 @@ pub trait Visitor<'ast>: Sized { fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) { walk_fn(self, fk, fd, s) } - fn visit_trait_item(&mut self, i: &'ast AssocItem) { walk_assoc_item(self, i) } - fn visit_impl_item(&mut self, i: &'ast AssocItem) { walk_assoc_item(self, i) } + fn visit_trait_item(&mut self, i: &'ast AssocItem) { walk_trait_item(self, i) } + fn visit_impl_item(&mut self, i: &'ast AssocItem) { walk_impl_item(self, i) } + fn visit_assoc_item(&mut self, i: &'ast AssocItem) { walk_assoc_item(self, i) } fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) } fn visit_param_bound(&mut self, bounds: &'ast GenericBound) { walk_param_bound(self, bounds) @@ -581,6 +582,14 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl } } +pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) { + visitor.visit_assoc_item(item); +} + +pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) { + visitor.visit_assoc_item(item); +} + pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) { visitor.visit_vis(&item.vis); visitor.visit_ident(item.ident); diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr index d9ebcdecb9bfd..1f61473c9d2f4 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr @@ -16,15 +16,6 @@ LL | type Baa = impl Debug; = note: for more information, see https://github.com/rust-lang/rust/issues/63063 = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable -error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18 - | -LL | type Assoc = impl Debug; - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/63063 - = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable - error[E0658]: associated type defaults are unstable --> $DIR/feature-gate-type_alias_impl_trait.rs:18:5 | @@ -34,6 +25,15 @@ LL | type Assoc = impl Debug; = note: for more information, see https://github.com/rust-lang/rust/issues/29661 = help: add `#![feature(associated_type_defaults)]` to the crate attributes to enable +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18 + | +LL | type Assoc = impl Debug; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/63063 + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + error[E0658]: `impl Trait` in type aliases is unstable --> $DIR/feature-gate-type_alias_impl_trait.rs:24:24 | diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs index b67e30637aa62..09f967f161ede 100644 --- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs +++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs @@ -1,3 +1,5 @@ +#![feature(specialization)] + fn main() {} trait X { diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr index 48b502a1506b1..54111df342343 100644 --- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr +++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr @@ -1,35 +1,35 @@ error: `default` is only allowed on items in `impl` definitions - --> $DIR/trait-item-with-defaultness-fail-semantic.rs:4:5 + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5 | LL | default const A: u8; | ^^^^^^^^^^^^^^^^^^^^ error: `default` is only allowed on items in `impl` definitions - --> $DIR/trait-item-with-defaultness-fail-semantic.rs:5:5 + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5 | LL | default const B: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `default` is only allowed on items in `impl` definitions - --> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5 + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5 | LL | default type D; | ^^^^^^^^^^^^^^^ error: `default` is only allowed on items in `impl` definitions - --> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5 + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5 | LL | default type C: Ord; | ^^^^^^^^^^^^^^^^^^^^ error: `default` is only allowed on items in `impl` definitions - --> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5 + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:10:5 | LL | default fn f1(); | ^^^^^^^^^^^^^^^^ error: `default` is only allowed on items in `impl` definitions - --> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5 + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:11:5 | LL | default fn f2() {} | ^^^^^^^^^^^^^^^^^^ From 0d41d0fe1423b4d21d6a9a2778419d399da1a13a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 02:38:33 +0100 Subject: [PATCH 22/38] Move `allow_c_varadic` logic to `ast_validation`. --- src/librustc_parse/parser/item.rs | 16 +------- src/librustc_parse/parser/ty.rs | 5 +-- src/librustc_passes/ast_validation.rs | 26 +++++++++++++ .../ui/invalid/invalid-variadic-function.rs | 3 -- .../invalid/invalid-variadic-function.stderr | 15 -------- src/test/ui/parser/variadic-ffi-3.rs | 5 --- src/test/ui/parser/variadic-ffi-3.stderr | 9 ----- src/test/ui/parser/variadic-ffi-4.rs | 5 --- src/test/ui/parser/variadic-ffi-4.stderr | 9 ----- .../variadic-ffi-semantic-restrictions.rs | 26 +++++++++++++ .../variadic-ffi-semantic-restrictions.stderr | 38 +++++++++++++++++++ .../ui/parser/variadic-ffi-syntactic-pass.rs | 25 ++++++++++++ 12 files changed, 119 insertions(+), 63 deletions(-) delete mode 100644 src/test/ui/invalid/invalid-variadic-function.rs delete mode 100644 src/test/ui/invalid/invalid-variadic-function.stderr delete mode 100644 src/test/ui/parser/variadic-ffi-3.rs delete mode 100644 src/test/ui/parser/variadic-ffi-3.stderr delete mode 100644 src/test/ui/parser/variadic-ffi-4.rs delete mode 100644 src/test/ui/parser/variadic-ffi-4.stderr create mode 100644 src/test/ui/parser/variadic-ffi-semantic-restrictions.rs create mode 100644 src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr create mode 100644 src/test/ui/parser/variadic-ffi-syntactic-pass.rs diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 0126297a3586e..d4b62e8ebba6b 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1727,8 +1727,6 @@ impl<'a> Parser<'a> { pub(super) struct ParamCfg { /// Is `self` is allowed as the first parameter? pub is_self_allowed: bool, - /// Is `...` allowed as the tail of the parameter list? - pub allow_c_variadic: bool, /// `is_name_required` decides if, per-parameter, /// the parameter must have a pattern or just a type. pub is_name_required: fn(&token::Token) -> bool, @@ -1744,16 +1742,8 @@ impl<'a> Parser<'a> { attrs: Vec, header: FnHeader, ) -> PResult<'a, Option>> { - let is_c_abi = match header.ext { - ast::Extern::None => false, - ast::Extern::Implicit => true, - ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C, - }; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, - // FIXME: Parsing should not depend on ABI or unsafety and - // the variadic parameter should always be parsed. - allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe, is_name_required: |_| true, })?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; @@ -1772,7 +1762,6 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Fn)?; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, - allow_c_variadic: true, is_name_required: |_| true, })?; let span = lo.to(self.token.span); @@ -1797,7 +1786,6 @@ impl<'a> Parser<'a> { let header = self.parse_fn_front_matter()?; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: true, - allow_c_variadic: false, is_name_required, })?; let sig = FnSig { header, decl }; @@ -1993,12 +1981,12 @@ impl<'a> Parser<'a> { } self.eat_incorrect_doc_comment_for_param_type(); - (pat, self.parse_ty_for_param(cfg.allow_c_variadic)?) + (pat, self.parse_ty_for_param()?) } else { debug!("parse_param_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); self.eat_incorrect_doc_comment_for_param_type(); - let mut ty = self.parse_ty_for_param(cfg.allow_c_variadic); + let mut ty = self.parse_ty_for_param(); if ty.is_ok() && self.token != token::Comma && self.token != token::CloseDelim(token::Paren) { // This wasn't actually a type, but a pattern looking like a type, diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 1dffa6c94a898..3ab290d1cbbc5 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -33,8 +33,8 @@ impl<'a> Parser<'a> { /// Parse a type suitable for a function or function pointer parameter. /// The difference from `parse_ty` is that this version allows `...` /// (`CVarArgs`) at the top level of the the type. - pub(super) fn parse_ty_for_param(&mut self, allow_c_variadic: bool) -> PResult<'a, P> { - self.parse_ty_common(true, true, allow_c_variadic) + pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P> { + self.parse_ty_common(true, true, true) } /// Parses a type in restricted contexts where `+` is not permitted. @@ -306,7 +306,6 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Fn)?; let cfg = ParamCfg { is_self_allowed: false, - allow_c_variadic: true, is_name_required: |_| false, }; let decl = self.parse_fn_decl(cfg, false)?; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index ad6c99494a60f..a26c991c9cfb2 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -306,6 +306,19 @@ impl<'a> AstValidator<'a> { .struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect") .emit(); } + + fn check_c_varadic_type(&self, decl: &FnDecl) { + for Param { ty, span, .. } in &decl.inputs { + if let TyKind::CVarArgs = ty.kind { + self.err_handler() + .struct_span_err( + *span, + "only foreign or `unsafe extern \"C\" functions may be C-variadic", + ) + .emit(); + } + } + } } enum GenericPosition { @@ -554,6 +567,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } + // Reject C-varadic type unless the function is `unsafe extern "C"` semantically. + match sig.header.ext { + Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | + Extern::Implicit if sig.header.unsafety == Unsafety::Unsafe => {} + _ => self.check_c_varadic_type(&sig.decl), + } } ItemKind::ForeignMod(..) => { self.invalid_visibility( @@ -795,6 +814,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_defaultness(ti.span, ti.defaultness); visit::walk_trait_item(self, ti); } + + fn visit_assoc_item(&mut self, item: &'a AssocItem) { + if let AssocItemKind::Method(sig, _) = &item.kind { + self.check_c_varadic_type(&sig.decl); + } + visit::walk_assoc_item(self, item); + } } pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool { diff --git a/src/test/ui/invalid/invalid-variadic-function.rs b/src/test/ui/invalid/invalid-variadic-function.rs deleted file mode 100644 index 8d23f0e477077..0000000000000 --- a/src/test/ui/invalid/invalid-variadic-function.rs +++ /dev/null @@ -1,3 +0,0 @@ -extern "C" fn foo(x: u8, ...); -//~^ ERROR only foreign functions are allowed to be C-variadic -//~| ERROR expected one of `->`, `where`, or `{`, found `;` diff --git a/src/test/ui/invalid/invalid-variadic-function.stderr b/src/test/ui/invalid/invalid-variadic-function.stderr deleted file mode 100644 index 7e58b17e7db74..0000000000000 --- a/src/test/ui/invalid/invalid-variadic-function.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0743]: only foreign functions are allowed to be C-variadic - --> $DIR/invalid-variadic-function.rs:1:26 - | -LL | extern "C" fn foo(x: u8, ...); - | ^^^ - -error: expected one of `->`, `where`, or `{`, found `;` - --> $DIR/invalid-variadic-function.rs:1:30 - | -LL | extern "C" fn foo(x: u8, ...); - | ^ expected one of `->`, `where`, or `{` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/parser/variadic-ffi-3.rs b/src/test/ui/parser/variadic-ffi-3.rs deleted file mode 100644 index ce83cc87abe00..0000000000000 --- a/src/test/ui/parser/variadic-ffi-3.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn foo(x: isize, ...) { - //~^ ERROR: only foreign functions are allowed to be C-variadic -} - -fn main() {} diff --git a/src/test/ui/parser/variadic-ffi-3.stderr b/src/test/ui/parser/variadic-ffi-3.stderr deleted file mode 100644 index aeeebdb991483..0000000000000 --- a/src/test/ui/parser/variadic-ffi-3.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0743]: only foreign functions are allowed to be C-variadic - --> $DIR/variadic-ffi-3.rs:1:18 - | -LL | fn foo(x: isize, ...) { - | ^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/parser/variadic-ffi-4.rs b/src/test/ui/parser/variadic-ffi-4.rs deleted file mode 100644 index 5f8b3f8f539b8..0000000000000 --- a/src/test/ui/parser/variadic-ffi-4.rs +++ /dev/null @@ -1,5 +0,0 @@ -extern "C" fn foo(x: isize, ...) { - //~^ ERROR: only foreign functions are allowed to be C-variadic -} - -fn main() {} diff --git a/src/test/ui/parser/variadic-ffi-4.stderr b/src/test/ui/parser/variadic-ffi-4.stderr deleted file mode 100644 index da83276c72dd1..0000000000000 --- a/src/test/ui/parser/variadic-ffi-4.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0743]: only foreign functions are allowed to be C-variadic - --> $DIR/variadic-ffi-4.rs:1:29 - | -LL | extern "C" fn foo(x: isize, ...) { - | ^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs new file mode 100644 index 0000000000000..57086bca2f428 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -0,0 +1,26 @@ +#![feature(c_variadic)] + +fn main() {} + +fn f1(x: isize, ...) {} +//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + +extern "C" fn f2(x: isize, ...) {} +//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + +extern fn f3(x: isize, ...) {} +//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + +struct X; + +impl X { + fn f4(x: isize, ...) {} + //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +} + +trait T { + fn f5(x: isize, ...) {} + //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + fn f6(x: isize, ...); + //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +} diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr new file mode 100644 index 0000000000000..69244d92ee392 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -0,0 +1,38 @@ +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:5:17 + | +LL | fn f1(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:8:28 + | +LL | extern "C" fn f2(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:11:24 + | +LL | extern fn f3(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:17:21 + | +LL | fn f4(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:22:21 + | +LL | fn f5(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:24:21 + | +LL | fn f6(x: isize, ...); + | ^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/variadic-ffi-syntactic-pass.rs b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs new file mode 100644 index 0000000000000..f8fcce6ba73f5 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs @@ -0,0 +1,25 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +fn f1(x: isize, ...) {} + +#[cfg(FALSE)] +extern "C" fn f2(x: isize, ...) {} + +#[cfg(FALSE)] +extern fn f3(x: isize, ...) {} + +struct X; + +#[cfg(FALSE)] +impl X { + fn f4(x: isize, ...) {} +} + +#[cfg(FALSE)] +trait T { + fn f5(x: isize, ...) {} + fn f6(x: isize, ...); +} From 3a57a2cca489da43fa3168aa1cb453e2b175a1f6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 02:53:18 +0100 Subject: [PATCH 23/38] `ast_validation`: move trait item logic to proper place. --- src/librustc_passes/ast_validation.rs | 43 ++++++++++++++------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index a26c991c9cfb2..884af188ed64c 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -608,26 +608,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } self.no_questions_in_bounds(bounds, "supertraits", true); - for trait_item in trait_items { - if let TraitItemKind::Method(ref sig, ref block) = trait_item.kind { - self.check_fn_decl(&sig.decl); - self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node); - self.check_trait_fn_not_const(sig.header.constness); - if block.is_none() { - Self::check_decl_no_pat(&sig.decl, |span, mut_ident| { - if mut_ident { - self.lint_buffer.buffer_lint( - lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, - trait_item.id, span, - "patterns aren't allowed in methods without bodies"); - } else { - struct_span_err!(self.session, span, E0642, - "patterns aren't allowed in methods without bodies").emit(); - } - }); - } - } - } } ItemKind::Mod(_) => { // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). @@ -812,6 +792,29 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_trait_item(&mut self, ti: &'a AssocItem) { self.invalid_visibility(&ti.vis, None); self.check_defaultness(ti.span, ti.defaultness); + + if let AssocItemKind::Method(sig, block) = &ti.kind { + self.check_fn_decl(&sig.decl); + self.check_trait_fn_not_async(ti.span, sig.header.asyncness.node); + self.check_trait_fn_not_const(sig.header.constness); + if block.is_none() { + Self::check_decl_no_pat(&sig.decl, |span, mut_ident| { + if mut_ident { + self.lint_buffer.buffer_lint( + lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, + ti.id, span, + "patterns aren't allowed in methods without bodies" + ); + } else { + struct_span_err!( + self.session, span, E0642, + "patterns aren't allowed in methods without bodies" + ).emit(); + } + }); + } + } + visit::walk_trait_item(self, ti); } From 35e9e097e7c7e977f36795c0febceb327e1fa33f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 03:16:12 +0100 Subject: [PATCH 24/38] More c-variadic errors as semantic restrictions. --- src/librustc/hir/lowering.rs | 8 +- src/librustc_parse/parser/item.rs | 55 +---- src/librustc_passes/ast_validation.rs | 23 +- .../variadic-ffi-no-fixed-args.stderr | 4 +- .../variadic-ffi-semantic-restrictions.rs | 74 +++++-- .../variadic-ffi-semantic-restrictions.stderr | 204 ++++++++++++++++-- .../ui/parser/variadic-ffi-syntactic-pass.rs | 40 +++- 7 files changed, 322 insertions(+), 86 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e2c99f456e988..58225e87f2682 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1426,7 +1426,13 @@ impl<'a> LoweringContext<'a> { } } TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"), - TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"), + TyKind::CVarArgs => { + self.sess.delay_span_bug( + t.span, + "`TyKind::CVarArgs` should have been handled elsewhere", + ); + hir::TyKind::Err + } }; hir::Ty { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d4b62e8ebba6b..a7c9888662280 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1885,58 +1885,23 @@ impl<'a> Parser<'a> { /// Parses the parameter list of a function, including the `(` and `)` delimiters. fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec> { - let sp = self.token.span; let is_trait_item = cfg.is_self_allowed; - let mut c_variadic = false; // Parse the arguments, starting out with `self` being possibly allowed... - let (params, _) = self.parse_paren_comma_seq(|p| { - let param = p.parse_param_general(&cfg, is_trait_item); + let (mut params, _) = self.parse_paren_comma_seq(|p| { + let param = p.parse_param_general(&cfg, is_trait_item).or_else(|mut e| { + e.emit(); + let lo = p.prev_span; + // Skip every token until next possible arg or end. + p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); + // Create a placeholder argument for proper arg count (issue #34264). + Ok(dummy_arg(Ident::new(kw::Invalid, lo.to(p.prev_span)))) + }); // ...now that we've parsed the first argument, `self` is no longer allowed. cfg.is_self_allowed = false; - - match param { - Ok(param) => Ok( - if let TyKind::CVarArgs = param.ty.kind { - c_variadic = true; - if p.token != token::CloseDelim(token::Paren) { - p.span_err( - p.token.span, - "`...` must be the last argument of a C-variadic function", - ); - // FIXME(eddyb) this should probably still push `CVarArgs`. - // Maybe AST validation/HIR lowering should emit the above error? - None - } else { - Some(param) - } - } else { - Some(param) - } - ), - Err(mut e) => { - e.emit(); - let lo = p.prev_span; - // Skip every token until next possible arg or end. - p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); - // Create a placeholder argument for proper arg count (issue #34264). - let span = lo.to(p.prev_span); - Ok(Some(dummy_arg(Ident::new(kw::Invalid, span)))) - } - } + param })?; - - let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); - // Replace duplicated recovered params with `_` pattern to avoid unnecessary errors. self.deduplicate_recovered_params_names(&mut params); - - if c_variadic && params.len() <= 1 { - self.span_err( - sp, - "C-variadic function must be declared with at least one named argument", - ); - } - Ok(params) } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 884af188ed64c..c75bd996e10c1 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -250,6 +250,26 @@ impl<'a> AstValidator<'a> { } fn check_fn_decl(&self, fn_decl: &FnDecl) { + match &*fn_decl.inputs { + [Param { ty, span, .. }] => if let TyKind::CVarArgs = ty.kind { + self.err_handler() + .span_err( + *span, + "C-variadic function must be declared with at least one named argument", + ); + }, + [ps @ .., _] => for Param { ty, span, .. } in ps { + if let TyKind::CVarArgs = ty.kind { + self.err_handler() + .span_err( + *span, + "`...` must be the last argument of a C-variadic function", + ); + } + } + _ => {} + } + fn_decl .inputs .iter() @@ -265,8 +285,7 @@ impl<'a> AstValidator<'a> { ) .span_label(attr.span, "doc comments are not allowed here") .emit(); - } - else { + } else { self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \ forbid, and warn are the only allowed built-in attributes in function parameters") }); diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr index cb6060525fc0d..7af38c88f4334 100644 --- a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr @@ -1,8 +1,8 @@ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-no-fixed-args.rs:2:11 + --> $DIR/variadic-ffi-no-fixed-args.rs:2:12 | LL | fn foo(...); - | ^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs index 57086bca2f428..aa85f6d6b522b 100644 --- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -2,25 +2,75 @@ fn main() {} -fn f1(x: isize, ...) {} -//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +fn f1_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic -extern "C" fn f2(x: isize, ...) {} -//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +fn f1_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument -extern fn f3(x: isize, ...) {} -//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +extern "C" fn f2_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + +extern "C" fn f2_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern "C" fn f2_3(..., x: isize) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR `...` must be the last argument of a C-variadic function + +extern fn f3_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + +extern fn f3_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern fn f3_3(..., x: isize) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR `...` must be the last argument of a C-variadic function + +extern { + fn e_f1(...); + //~^ ERROR C-variadic function must be declared with at least one named argument + fn e_f2(..., x: isize); + //~^ ERROR `...` must be the last argument of a C-variadic function +} struct X; impl X { - fn f4(x: isize, ...) {} - //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + fn i_f1(x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + fn i_f2(...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn i_f3(..., x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function + fn i_f4(..., x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function } trait T { - fn f5(x: isize, ...) {} - //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic - fn f6(x: isize, ...); - //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + fn t_f1(x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + fn t_f2(x: isize, ...); + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + fn t_f3(...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn t_f4(...); + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn t_f5(..., x: isize) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function + fn t_f6(..., x: isize); + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function } diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr index 69244d92ee392..21992a29670c9 100644 --- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -1,38 +1,206 @@ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:5:17 + --> $DIR/variadic-ffi-semantic-restrictions.rs:5:19 | -LL | fn f1(x: isize, ...) {} - | ^^^^ +LL | fn f1_1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9 + | +LL | fn f1_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9 + | +LL | fn f1_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30 + | +LL | extern "C" fn f2_1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 + | +LL | extern "C" fn f2_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 + | +LL | extern "C" fn f2_2(...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20 + | +LL | extern "C" fn f2_3(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20 + | +LL | extern "C" fn f2_3(..., x: isize) {} + | ^^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:8:28 + --> $DIR/variadic-ffi-semantic-restrictions.rs:23:26 | -LL | extern "C" fn f2(x: isize, ...) {} +LL | extern fn f3_1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16 + | +LL | extern fn f3_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16 + | +LL | extern fn f3_2(...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16 + | +LL | extern fn f3_3(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16 + | +LL | extern fn f3_3(..., x: isize) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:35:13 + | +LL | fn e_f1(...); + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:37:13 + | +LL | fn e_f2(..., x: isize); + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:23 + | +LL | fn i_f1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13 + | +LL | fn i_f2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13 + | +LL | fn i_f2(...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:49:28 + | +LL | fn i_f3(..., x: isize, ...) {} | ^^^^ +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^^ + error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:11:24 + --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13 | -LL | extern fn f3(x: isize, ...) {} - | ^^^^ +LL | fn i_f4(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:53:28 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:17:21 + --> $DIR/variadic-ffi-semantic-restrictions.rs:60:23 | -LL | fn f4(x: isize, ...) {} - | ^^^^ +LL | fn t_f1(x: isize, ...) {} + | ^^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:22:21 + --> $DIR/variadic-ffi-semantic-restrictions.rs:62:23 + | +LL | fn t_f2(x: isize, ...); + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 + | +LL | fn t_f3(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 + | +LL | fn t_f3(...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 + | +LL | fn t_f4(...); + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 + | +LL | fn t_f4(...); + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13 + | +LL | fn t_f5(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13 + | +LL | fn t_f5(..., x: isize) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13 | -LL | fn f5(x: isize, ...) {} - | ^^^^ +LL | fn t_f6(..., x: isize); + | ^^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:24:21 + --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13 | -LL | fn f6(x: isize, ...); - | ^^^^ +LL | fn t_f6(..., x: isize); + | ^^^^ -error: aborting due to 6 previous errors +error: aborting due to 34 previous errors diff --git a/src/test/ui/parser/variadic-ffi-syntactic-pass.rs b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs index f8fcce6ba73f5..3875d6af13716 100644 --- a/src/test/ui/parser/variadic-ffi-syntactic-pass.rs +++ b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs @@ -3,23 +3,51 @@ fn main() {} #[cfg(FALSE)] -fn f1(x: isize, ...) {} +fn f1_1(x: isize, ...) {} #[cfg(FALSE)] -extern "C" fn f2(x: isize, ...) {} +fn f1_2(...) {} #[cfg(FALSE)] -extern fn f3(x: isize, ...) {} +extern "C" fn f2_1(x: isize, ...) {} + +#[cfg(FALSE)] +extern "C" fn f2_2(...) {} + +#[cfg(FALSE)] +extern "C" fn f2_3(..., x: isize) {} + +#[cfg(FALSE)] +extern fn f3_1(x: isize, ...) {} + +#[cfg(FALSE)] +extern fn f3_2(...) {} + +#[cfg(FALSE)] +extern fn f3_3(..., x: isize) {} + +#[cfg(FALSE)] +extern { + fn e_f1(...); + fn e_f2(..., x: isize); +} struct X; #[cfg(FALSE)] impl X { - fn f4(x: isize, ...) {} + fn i_f1(x: isize, ...) {} + fn i_f2(...) {} + fn i_f3(..., x: isize, ...) {} + fn i_f4(..., x: isize, ...) {} } #[cfg(FALSE)] trait T { - fn f5(x: isize, ...) {} - fn f6(x: isize, ...); + fn t_f1(x: isize, ...) {} + fn t_f2(x: isize, ...); + fn t_f3(...) {} + fn t_f4(...); + fn t_f5(..., x: isize) {} + fn t_f6(..., x: isize); } From abf2e7aa959a4611bc2f607bc7e9200b8b81c089 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Dec 2019 00:08:09 +0100 Subject: [PATCH 25/38] Remove `ast::{Impl,Trait}{Item,ItemKind}`. --- src/librustc/hir/lowering.rs | 6 +-- src/librustc/hir/lowering/item.rs | 46 ++++++++++----------- src/librustc/lint/context.rs | 4 +- src/librustc/lint/mod.rs | 8 ++-- src/librustc_interface/util.rs | 15 +++---- src/librustc_lint/builtin.rs | 8 ++-- src/librustc_passes/ast_validation.rs | 2 +- src/librustc_passes/hir_stats.rs | 4 +- src/librustc_resolve/build_reduced_graph.rs | 18 ++++---- src/librustc_resolve/def_collector.rs | 20 ++++----- src/librustc_resolve/late.rs | 26 ++++++------ src/librustc_save_analysis/dump_visitor.rs | 26 ++++++------ src/libsyntax/ast.rs | 14 ++----- src/libsyntax/feature_gate/check.rs | 6 +-- src/libsyntax/token.rs | 4 +- src/libsyntax_expand/base.rs | 24 +++++------ src/libsyntax_expand/expand.rs | 4 +- src/libsyntax_expand/placeholders.rs | 8 ++-- src/libsyntax_ext/deriving/generic/mod.rs | 14 +++---- 19 files changed, 123 insertions(+), 134 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 58225e87f2682..78df14adc5d6d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -477,11 +477,11 @@ impl<'a> LoweringContext<'a> { }); } - fn visit_trait_item(&mut self, item: &'tcx TraitItem) { + fn visit_trait_item(&mut self, item: &'tcx AssocItem) { self.lctx.allocate_hir_id_counter(item.id); match item.kind { - TraitItemKind::Method(_, None) => { + AssocItemKind::Method(_, None) => { // Ignore patterns in trait methods without bodies self.with_hir_id_owner(None, |this| { visit::walk_trait_item(this, item) @@ -493,7 +493,7 @@ impl<'a> LoweringContext<'a> { } } - fn visit_impl_item(&mut self, item: &'tcx ImplItem) { + fn visit_impl_item(&mut self, item: &'tcx AssocItem) { self.lctx.allocate_hir_id_counter(item.id); self.with_hir_id_owner(Some(item.id), |this| { visit::walk_impl_item(this, item); diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index c3d2ed6b39cd2..f25714f741b8d 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -86,7 +86,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { } } - fn visit_trait_item(&mut self, item: &'tcx TraitItem) { + fn visit_trait_item(&mut self, item: &'tcx AssocItem) { self.lctx.with_hir_id_owner(item.id, |lctx| { let hir_item = lctx.lower_trait_item(item); let id = hir::TraitItemId { hir_id: hir_item.hir_id }; @@ -97,7 +97,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { visit::walk_assoc_item(self, item); } - fn visit_impl_item(&mut self, item: &'tcx ImplItem) { + fn visit_impl_item(&mut self, item: &'tcx AssocItem) { self.lctx.with_hir_id_owner(item.id, |lctx| { let hir_item = lctx.lower_impl_item(item); let id = hir::ImplItemId { hir_id: hir_item.hir_id }; @@ -813,11 +813,11 @@ impl LoweringContext<'_> { } } - fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem { + fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem { let trait_item_def_id = self.resolver.definitions().local_def_id(i.id); let (generics, kind) = match i.kind { - TraitItemKind::Const(ref ty, ref default) => ( + AssocItemKind::Const(ref ty, ref default) => ( self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::TraitItemKind::Const( self.lower_ty(ty, ImplTraitContext::disallowed()), @@ -826,7 +826,7 @@ impl LoweringContext<'_> { .map(|x| self.lower_const_body(i.span, Some(x))), ), ), - TraitItemKind::Method(ref sig, None) => { + AssocItemKind::Method(ref sig, None) => { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig( &i.generics, @@ -837,7 +837,7 @@ impl LoweringContext<'_> { ); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } - TraitItemKind::Method(ref sig, Some(ref body)) => { + AssocItemKind::Method(ref sig, Some(ref body)) => { let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = self.lower_method_sig( &i.generics, @@ -848,7 +848,7 @@ impl LoweringContext<'_> { ); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) } - TraitItemKind::TyAlias(ref bounds, ref default) => { + AssocItemKind::TyAlias(ref bounds, ref default) => { let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); let kind = hir::TraitItemKind::Type( self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), @@ -859,7 +859,7 @@ impl LoweringContext<'_> { (generics, kind) }, - TraitItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"), + AssocItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"), }; hir::TraitItem { @@ -872,21 +872,21 @@ impl LoweringContext<'_> { } } - fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef { + fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { let (kind, has_default) = match i.kind { - TraitItemKind::Const(_, ref default) => { + AssocItemKind::Const(_, ref default) => { (hir::AssocItemKind::Const, default.is_some()) } - TraitItemKind::TyAlias(_, ref default) => { + AssocItemKind::TyAlias(_, ref default) => { (hir::AssocItemKind::Type, default.is_some()) } - TraitItemKind::Method(ref sig, ref default) => ( + AssocItemKind::Method(ref sig, ref default) => ( hir::AssocItemKind::Method { has_self: sig.decl.has_self(), }, default.is_some(), ), - TraitItemKind::Macro(..) => unimplemented!(), + AssocItemKind::Macro(..) => unimplemented!(), }; hir::TraitItemRef { id: hir::TraitItemId { hir_id: self.lower_node_id(i.id) }, @@ -902,18 +902,18 @@ impl LoweringContext<'_> { self.expr(span, hir::ExprKind::Err, ThinVec::new()) } - fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem { + fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem { let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); let (generics, kind) = match i.kind { - ImplItemKind::Const(ref ty, ref expr) => ( + AssocItemKind::Const(ref ty, ref expr) => ( self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::ImplItemKind::Const( self.lower_ty(ty, ImplTraitContext::disallowed()), self.lower_const_body(i.span, expr.as_deref()), ), ), - ImplItemKind::Method(ref sig, ref body) => { + AssocItemKind::Method(ref sig, ref body) => { self.current_item = Some(i.span); let body_id = self.lower_maybe_async_body( i.span, @@ -932,7 +932,7 @@ impl LoweringContext<'_> { (generics, hir::ImplItemKind::Method(sig, body_id)) } - ImplItemKind::TyAlias(_, ref ty) => { + AssocItemKind::TyAlias(_, ref ty) => { let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); let kind = match ty { None => { @@ -951,7 +951,7 @@ impl LoweringContext<'_> { }; (generics, kind) }, - ImplItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"), + AssocItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"), }; hir::ImplItem { @@ -968,7 +968,7 @@ impl LoweringContext<'_> { // [1] since `default impl` is not yet implemented, this is always true in impls } - fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef { + fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { hir::ImplItemRef { id: hir::ImplItemId { hir_id: self.lower_node_id(i.id) }, ident: i.ident, @@ -976,18 +976,18 @@ impl LoweringContext<'_> { vis: self.lower_visibility(&i.vis, Some(i.id)), defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), kind: match &i.kind { - ImplItemKind::Const(..) => hir::AssocItemKind::Const, - ImplItemKind::TyAlias(_, ty) => match ty + AssocItemKind::Const(..) => hir::AssocItemKind::Const, + AssocItemKind::TyAlias(_, ty) => match ty .as_deref() .and_then(|ty| ty.kind.opaque_top_hack()) { None => hir::AssocItemKind::Type, Some(_) => hir::AssocItemKind::OpaqueTy, }, - ImplItemKind::Method(sig, _) => hir::AssocItemKind::Method { + AssocItemKind::Method(sig, _) => hir::AssocItemKind::Method { has_self: sig.decl.has_self(), }, - ImplItemKind::Macro(..) => unimplemented!(), + AssocItemKind::Macro(..) => unimplemented!(), }, } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7f72154e42c61..0fdd509a0bbec 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1249,7 +1249,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> ast_visit::walk_poly_trait_ref(self, t, m); } - fn visit_trait_item(&mut self, trait_item: &'a ast::TraitItem) { + fn visit_trait_item(&mut self, trait_item: &'a ast::AssocItem) { self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| { run_early_pass!(cx, check_trait_item, trait_item); ast_visit::walk_trait_item(cx, trait_item); @@ -1257,7 +1257,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> }); } - fn visit_impl_item(&mut self, impl_item: &'a ast::ImplItem) { + fn visit_impl_item(&mut self, impl_item: &'a ast::AssocItem) { self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| { run_early_pass!(cx, check_impl_item, impl_item); ast_visit::walk_impl_item(cx, impl_item); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index a8d886866795e..0054f149f8c27 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -258,10 +258,10 @@ macro_rules! early_lint_methods { c: Span, d: ast::NodeId ); - fn check_trait_item(a: &ast::TraitItem); - fn check_trait_item_post(a: &ast::TraitItem); - fn check_impl_item(a: &ast::ImplItem); - fn check_impl_item_post(a: &ast::ImplItem); + fn check_trait_item(a: &ast::AssocItem); + fn check_trait_item_post(a: &ast::AssocItem); + fn check_impl_item(a: &ast::AssocItem); + fn check_impl_item_post(a: &ast::AssocItem); fn check_struct_def(a: &ast::VariantData); fn check_struct_def_post(a: &ast::VariantData); fn check_struct_field(a: &ast::StructField); diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 026cb6eab1c7d..da8eae6028e36 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -776,22 +776,17 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { self.run(is_const, |s| noop_visit_item_kind(i, s)) } - fn flat_map_trait_item(&mut self, i: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { + fn flat_map_trait_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { let is_const = match i.kind { - ast::TraitItemKind::Const(..) => true, - ast::TraitItemKind::Method(ref sig, _) => Self::is_sig_const(sig), + ast::AssocItemKind::Const(..) => true, + ast::AssocItemKind::Method(ref sig, _) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) } - fn flat_map_impl_item(&mut self, i: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { - let is_const = match i.kind { - ast::ImplItemKind::Const(..) => true, - ast::ImplItemKind::Method(ref sig, _) => Self::is_sig_const(sig), - _ => false, - }; - self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) + fn flat_map_impl_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { + self.flat_map_trait_item(i) } fn visit_anon_const(&mut self, c: &mut ast::AnonConst) { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 10b00d35d9bca..8916fc0883871 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -268,8 +268,8 @@ impl EarlyLintPass for UnsafeCode { } } - fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::TraitItem) { - if let ast::TraitItemKind::Method(ref sig, None) = item.kind { + fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::AssocItem) { + if let ast::AssocItemKind::Method(ref sig, None) = item.kind { if sig.header.unsafety == ast::Unsafety::Unsafe { self.report_unsafe(cx, item.span, "declaration of an `unsafe` method") } @@ -615,9 +615,9 @@ declare_lint_pass!( ); impl EarlyLintPass for AnonymousParameters { - fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::TraitItem) { + fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { match it.kind { - ast::TraitItemKind::Method(ref sig, _) => { + ast::AssocItemKind::Method(ref sig, _) => { for arg in sig.decl.inputs.iter() { match arg.pat.kind { ast::PatKind::Ident(_, ident, None) => { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index c75bd996e10c1..609885cb254b7 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -544,7 +544,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } for impl_item in impl_items { self.invalid_visibility(&impl_item.vis, None); - if let ImplItemKind::Method(ref sig, _) = impl_item.kind { + if let AssocItemKind::Method(ref sig, _) = impl_item.kind { self.check_trait_fn_not_const(sig.header.constness); self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node); } diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index a5924efefc2af..66ceb4212c8ac 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -314,12 +314,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_fn(self, fk, fd, s) } - fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) { + fn visit_trait_item(&mut self, ti: &'v ast::AssocItem) { self.record("TraitItem", Id::None, ti); ast_visit::walk_trait_item(self, ti) } - fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) { + fn visit_impl_item(&mut self, ii: &'v ast::AssocItem) { self.record("ImplItem", Id::None, ii); ast_visit::walk_impl_item(self, ii) } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index d2d5a33ec7aa9..dc3013754404b 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -30,7 +30,7 @@ use errors::Applicability; use syntax::ast::{Name, Ident}; use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; -use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind}; +use syntax::ast::{MetaItemKind, StmtKind, AssocItem, AssocItemKind}; use syntax::token::{self, Token}; use syntax::span_err; use syntax::source_map::{respan, Spanned}; @@ -1164,10 +1164,10 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { self.parent_scope.legacy = orig_current_legacy_scope; } - fn visit_trait_item(&mut self, item: &'b TraitItem) { + fn visit_trait_item(&mut self, item: &'b AssocItem) { let parent = self.parent_scope.module; - if let TraitItemKind::Macro(_) = item.kind { + if let AssocItemKind::Macro(_) = item.kind { self.visit_invoc(item.id); return } @@ -1175,15 +1175,15 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { // Add the item to the trait info. let item_def_id = self.r.definitions.local_def_id(item.id); let (res, ns) = match item.kind { - TraitItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), - TraitItemKind::Method(ref sig, _) => { + AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), + AssocItemKind::Method(ref sig, _) => { if sig.decl.has_self() { self.r.has_self.insert(item_def_id); } (Res::Def(DefKind::Method, item_def_id), ValueNS) } - TraitItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS), - TraitItemKind::Macro(_) => bug!(), // handled above + AssocItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS), + AssocItemKind::Macro(_) => bug!(), // handled above }; let vis = ty::Visibility::Public; @@ -1193,8 +1193,8 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { visit::walk_trait_item(self, item); } - fn visit_impl_item(&mut self, item: &'b ast::ImplItem) { - if let ast::ImplItemKind::Macro(..) = item.kind { + fn visit_impl_item(&mut self, item: &'b ast::AssocItem) { + if let ast::AssocItemKind::Macro(..) = item.kind { self.visit_invoc(item.id); } else { self.resolve_visibility(&item.vis); diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 471e2634b8acf..6e26553d82f82 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -212,23 +212,23 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { visit::walk_generic_param(self, param); } - fn visit_trait_item(&mut self, ti: &'a TraitItem) { + fn visit_trait_item(&mut self, ti: &'a AssocItem) { let def_data = match ti.kind { - TraitItemKind::Method(..) | TraitItemKind::Const(..) => + AssocItemKind::Method(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name), - TraitItemKind::TyAlias(..) => { + AssocItemKind::TyAlias(..) => { DefPathData::TypeNs(ti.ident.name) }, - TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), + AssocItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), }; let def = self.create_def(ti.id, def_data, ti.span); self.with_parent(def, |this| visit::walk_trait_item(this, ti)); } - fn visit_impl_item(&mut self, ii: &'a ImplItem) { + fn visit_impl_item(&mut self, ii: &'a AssocItem) { let def_data = match ii.kind { - ImplItemKind::Method(FnSig { + AssocItemKind::Method(FnSig { ref header, ref decl, }, ref body) if header.asyncness.node.is_async() => { @@ -242,10 +242,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { body.as_deref(), ) } - ImplItemKind::Method(..) | - ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name), - ImplItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name), - ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), + AssocItemKind::Method(..) | + AssocItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name), + AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name), + AssocItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), }; let def = self.create_def(ii.id, def_data, ii.span); diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 682ddc421c287..ad29fd9e1db1e 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -806,7 +806,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { this.with_generic_param_rib(&trait_item.generics, AssocItemRibKind, |this| { match trait_item.kind { - TraitItemKind::Const(ref ty, ref default) => { + AssocItemKind::Const(ref ty, ref default) => { this.visit_ty(ty); // Only impose the restrictions of @@ -818,13 +818,13 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { }); } } - TraitItemKind::Method(_, _) => { + AssocItemKind::Method(_, _) => { visit::walk_assoc_item(this, trait_item) } - TraitItemKind::TyAlias(..) => { + AssocItemKind::TyAlias(..) => { visit::walk_assoc_item(this, trait_item) } - TraitItemKind::Macro(_) => { + AssocItemKind::Macro(_) => { panic!("unexpanded macro in resolve!") } }; @@ -989,13 +989,13 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { /// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412. fn with_trait_items( &mut self, - trait_items: &Vec, + trait_items: &Vec, f: impl FnOnce(&mut Self) -> T, ) -> T { let trait_assoc_types = replace( &mut self.diagnostic_metadata.current_trait_assoc_types, trait_items.iter().filter_map(|item| match &item.kind { - TraitItemKind::TyAlias(bounds, _) if bounds.len() == 0 => Some(item.ident), + AssocItemKind::TyAlias(bounds, _) if bounds.len() == 0 => Some(item.ident), _ => None, }).collect(), ); @@ -1063,7 +1063,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { opt_trait_reference: &Option, self_type: &Ty, item_id: NodeId, - impl_items: &[ImplItem]) { + impl_items: &[AssocItem]) { debug!("resolve_implementation"); // If applicable, create a rib for the type parameters. self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { @@ -1092,9 +1092,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { |this| { use crate::ResolutionError::*; match impl_item.kind { - ImplItemKind::Const(..) => { + AssocItemKind::Const(..) => { debug!( - "resolve_implementation ImplItemKind::Const", + "resolve_implementation AssocItemKind::Const", ); // If this is a trait impl, ensure the const // exists in trait @@ -1109,7 +1109,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { visit::walk_assoc_item(this, impl_item) }); } - ImplItemKind::Method(..) => { + AssocItemKind::Method(..) => { // If this is a trait impl, ensure the method // exists in trait this.check_trait_item(impl_item.ident, @@ -1119,7 +1119,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { visit::walk_assoc_item(this, impl_item); } - ImplItemKind::TyAlias(_, Some(ref ty)) => { + AssocItemKind::TyAlias(_, Some(ref ty)) => { // If this is a trait impl, ensure the type // exists in trait this.check_trait_item(impl_item.ident, @@ -1129,8 +1129,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { this.visit_ty(ty); } - ImplItemKind::TyAlias(_, None) => {} - ImplItemKind::Macro(_) => + AssocItemKind::TyAlias(_, None) => {} + AssocItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), } }); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index cc0f3c512f53e..3b36c1c70f9f2 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -676,7 +676,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { generics: &'l ast::Generics, trait_ref: &'l Option, typ: &'l ast::Ty, - impl_items: &'l [ast::ImplItem], + impl_items: &'l [ast::AssocItem], ) { if let Some(impl_data) = self.save_ctxt.get_item_data(item) { if !self.span.filter_generated(item.span) { @@ -707,7 +707,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { item: &'l ast::Item, generics: &'l ast::Generics, trait_refs: &'l ast::GenericBounds, - methods: &'l [ast::TraitItem], + methods: &'l [ast::AssocItem], ) { let name = item.ident.to_string(); let qualname = format!("::{}", @@ -1029,11 +1029,11 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { // } } - fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) { + fn process_trait_item(&mut self, trait_item: &'l ast::AssocItem, trait_id: DefId) { self.process_macro_use(trait_item.span); let vis_span = trait_item.span.shrink_to_lo(); match trait_item.kind { - ast::TraitItemKind::Const(ref ty, ref expr) => { + ast::AssocItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( trait_item.id, trait_item.ident, @@ -1044,7 +1044,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &trait_item.attrs, ); } - ast::TraitItemKind::Method(ref sig, ref body) => { + ast::AssocItemKind::Method(ref sig, ref body) => { self.process_method( sig, body.as_ref().map(|x| &**x), @@ -1055,7 +1055,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { trait_item.span, ); } - ast::TraitItemKind::TyAlias(ref bounds, ref default_ty) => { + ast::AssocItemKind::TyAlias(ref bounds, ref default_ty) => { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!("::{}", @@ -1097,14 +1097,14 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { self.visit_ty(default_ty) } } - ast::TraitItemKind::Macro(_) => {} + ast::AssocItemKind::Macro(_) => {} } } - fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) { + fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) { self.process_macro_use(impl_item.span); match impl_item.kind { - ast::ImplItemKind::Const(ref ty, ref expr) => { + ast::AssocItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( impl_item.id, impl_item.ident, @@ -1115,7 +1115,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &impl_item.attrs, ); } - ast::ImplItemKind::Method(ref sig, ref body) => { + ast::AssocItemKind::Method(ref sig, ref body) => { self.process_method( sig, body.as_deref(), @@ -1126,14 +1126,14 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { impl_item.span, ); } - ast::ImplItemKind::TyAlias(_, None) => {} - ast::ImplItemKind::TyAlias(_, Some(ref ty)) => { + ast::AssocItemKind::TyAlias(_, None) => {} + ast::AssocItemKind::TyAlias(_, Some(ref ty)) => { // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. self.visit_ty(ty) } - ast::ImplItemKind::Macro(_) => {} + ast::AssocItemKind::Macro(_) => {} } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d90d74d7a262c..1b729ebaf4376 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1603,16 +1603,10 @@ pub struct FnSig { pub decl: P, } -// FIXME(Centril): Remove all of these. -pub type TraitItem = AssocItem; -pub type TraitItemKind = AssocItemKind; -pub type ImplItem = AssocItem; -pub type ImplItemKind = AssocItemKind; - /// Represents associated items. /// These include items in `impl` and `trait` definitions. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct AssocItem { +pub struct AssocItem { pub attrs: Vec, pub id: NodeId, pub span: Span, @@ -1621,7 +1615,7 @@ pub struct AssocItem { pub defaultness: Defaultness, pub generics: Generics, - pub kind: K, + pub kind: AssocItemKind, /// See `Item::tokens` for what this is. pub tokens: Option, } @@ -2598,7 +2592,7 @@ pub enum ItemKind { /// A trait declaration (`trait`). /// /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. - Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec), + Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec), /// Trait alias /// /// E.g., `trait Foo = Bar + Quux;`. @@ -2613,7 +2607,7 @@ pub enum ItemKind { Generics, Option, // (optional) trait this impl implements P, // self - Vec, + Vec, ), /// A macro invocation. /// diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index c27fcb6a68e0f..fcce9d4e95f5a 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -571,9 +571,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_assoc_ty_constraint(self, constraint) } - fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) { + fn visit_trait_item(&mut self, ti: &'a ast::AssocItem) { match ti.kind { - ast::TraitItemKind::Method(ref sig, ref block) => { + ast::AssocItemKind::Method(ref sig, ref block) => { if block.is_none() { self.check_extern(sig.header.ext); } @@ -581,7 +581,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); } } - ast::TraitItemKind::TyAlias(_, ref default) => { + ast::AssocItemKind::TyAlias(_, ref default) => { if let Some(_) = default { gate_feature_post!( &self, associated_type_defaults, ti.span, diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs index 6f45211ac5f29..263f8192241f2 100644 --- a/src/libsyntax/token.rs +++ b/src/libsyntax/token.rs @@ -685,8 +685,8 @@ pub enum Nonterminal { // Used only for passing items to proc macro attributes (they are not // strictly necessary for that, `Annotatable` can be converted into // tokens directly, but doing that naively regresses pretty-printing). - NtTraitItem(ast::TraitItem), - NtImplItem(ast::ImplItem), + NtTraitItem(ast::AssocItem), + NtImplItem(ast::AssocItem), NtForeignItem(ast::ForeignItem), } diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax_expand/base.rs index a4449ca5b1d22..2cfcbd3161f4d 100644 --- a/src/libsyntax_expand/base.rs +++ b/src/libsyntax_expand/base.rs @@ -31,8 +31,8 @@ crate use syntax_pos::hygiene::MacroKind; #[derive(Debug,Clone)] pub enum Annotatable { Item(P), - TraitItem(P), - ImplItem(P), + TraitItem(P), + ImplItem(P), ForeignItem(P), Stmt(P), Expr(P), @@ -137,14 +137,14 @@ impl Annotatable { } } - pub fn expect_trait_item(self) -> ast::TraitItem { + pub fn expect_trait_item(self) -> ast::AssocItem { match self { Annotatable::TraitItem(i) => i.into_inner(), _ => panic!("expected Item") } } - pub fn expect_impl_item(self) -> ast::ImplItem { + pub fn expect_impl_item(self) -> ast::AssocItem { match self { Annotatable::ImplItem(i) => i.into_inner(), _ => panic!("expected Item") @@ -382,12 +382,12 @@ pub trait MacResult { } /// Creates zero or more impl items. - fn make_impl_items(self: Box) -> Option> { + fn make_impl_items(self: Box) -> Option> { None } /// Creates zero or more trait items. - fn make_trait_items(self: Box) -> Option> { + fn make_trait_items(self: Box) -> Option> { None } @@ -468,8 +468,8 @@ make_MacEager! { expr: P, pat: P, items: SmallVec<[P; 1]>, - impl_items: SmallVec<[ast::ImplItem; 1]>, - trait_items: SmallVec<[ast::TraitItem; 1]>, + impl_items: SmallVec<[ast::AssocItem; 1]>, + trait_items: SmallVec<[ast::AssocItem; 1]>, foreign_items: SmallVec<[ast::ForeignItem; 1]>, stmts: SmallVec<[ast::Stmt; 1]>, ty: P, @@ -484,11 +484,11 @@ impl MacResult for MacEager { self.items } - fn make_impl_items(self: Box) -> Option> { + fn make_impl_items(self: Box) -> Option> { self.impl_items } - fn make_trait_items(self: Box) -> Option> { + fn make_trait_items(self: Box) -> Option> { self.trait_items } @@ -588,11 +588,11 @@ impl MacResult for DummyResult { Some(SmallVec::new()) } - fn make_impl_items(self: Box) -> Option> { + fn make_impl_items(self: Box) -> Option> { Some(SmallVec::new()) } - fn make_trait_items(self: Box) -> Option> { + fn make_trait_items(self: Box) -> Option> { Some(SmallVec::new()) } diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs index 2eae6d494d07a..d4223af27abe6 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -155,10 +155,10 @@ ast_fragments! { Items(SmallVec<[P; 1]>) { "item"; many fn flat_map_item; fn visit_item; fn make_items; } - TraitItems(SmallVec<[ast::TraitItem; 1]>) { + TraitItems(SmallVec<[ast::AssocItem; 1]>) { "trait item"; many fn flat_map_trait_item; fn visit_trait_item; fn make_trait_items; } - ImplItems(SmallVec<[ast::ImplItem; 1]>) { + ImplItems(SmallVec<[ast::AssocItem; 1]>) { "impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items; } ForeignItems(SmallVec<[ast::ForeignItem; 1]>) { diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs index 18acbf2cc13d9..22e99baae5be0 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -50,15 +50,15 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option AstFragment::TraitItems(smallvec![ast::TraitItem { + AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::AssocItem { id, span, ident, vis, attrs, generics, - kind: ast::TraitItemKind::Macro(mac_placeholder()), + kind: ast::AssocItemKind::Macro(mac_placeholder()), defaultness: ast::Defaultness::Final, tokens: None, }]), - AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem { + AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::AssocItem { id, span, ident, vis, attrs, generics, - kind: ast::ImplItemKind::Macro(mac_placeholder()), + kind: ast::AssocItemKind::Macro(mac_placeholder()), defaultness: ast::Defaultness::Final, tokens: None, }]), diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index d51fcf315a69b..1c1fcc4f301bc 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -504,13 +504,13 @@ impl<'a> TraitDef<'a> { type_ident: Ident, generics: &Generics, field_tys: Vec>, - methods: Vec) + methods: Vec) -> P { let trait_path = self.path.to_path(cx, self.span, type_ident, generics); - // Transform associated types from `deriving::ty::Ty` into `ast::ImplItem` + // Transform associated types from `deriving::ty::Ty` into `ast::AssocItem` let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| { - ast::ImplItem { + ast::AssocItem { id: ast::DUMMY_NODE_ID, span: self.span, ident, @@ -518,7 +518,7 @@ impl<'a> TraitDef<'a> { defaultness: ast::Defaultness::Final, attrs: Vec::new(), generics: Generics::default(), - kind: ast::ImplItemKind::TyAlias( + kind: ast::AssocItemKind::TyAlias( Vec::new(), Some(type_def.to_ty(cx, self.span, type_ident, generics)), ), @@ -912,7 +912,7 @@ impl<'a> MethodDef<'a> { explicit_self: Option, arg_types: Vec<(Ident, P)>, body: P) - -> ast::ImplItem { + -> ast::AssocItem { // Create the generics that aren't for `Self`. let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics); @@ -950,7 +950,7 @@ impl<'a> MethodDef<'a> { }; // Create the method. - ast::ImplItem { + ast::AssocItem { id: ast::DUMMY_NODE_ID, attrs: self.attributes.clone(), generics: fn_generics, @@ -958,7 +958,7 @@ impl<'a> MethodDef<'a> { vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, ident: method_ident, - kind: ast::ImplItemKind::Method(sig, Some(body_block)), + kind: ast::AssocItemKind::Method(sig, Some(body_block)), tokens: None, } } From e52f902a8ab3a1abbb200607db4766d95b27bc8e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Dec 2019 00:13:59 +0100 Subject: [PATCH 26/38] `AssocImplKind::{Method -> Fn}`. --- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/lowering/item.rs | 10 +++++----- src/librustc_interface/util.rs | 2 +- src/librustc_lint/builtin.rs | 4 ++-- src/librustc_parse/parser/item.rs | 2 +- src/librustc_passes/ast_validation.rs | 8 ++++---- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/def_collector.rs | 11 ++++------- src/librustc_resolve/late.rs | 4 ++-- src/librustc_save_analysis/dump_visitor.rs | 4 ++-- src/libsyntax/ast.rs | 3 +-- src/libsyntax/feature_gate/check.rs | 4 ++-- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 4 ++-- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- 16 files changed, 31 insertions(+), 35 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 78df14adc5d6d..50733512faec8 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -481,7 +481,7 @@ impl<'a> LoweringContext<'a> { self.lctx.allocate_hir_id_counter(item.id); match item.kind { - AssocItemKind::Method(_, None) => { + AssocItemKind::Fn(_, None) => { // Ignore patterns in trait methods without bodies self.with_hir_id_owner(None, |this| { visit::walk_trait_item(this, item) diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index f25714f741b8d..f0543b9057d1f 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -826,7 +826,7 @@ impl LoweringContext<'_> { .map(|x| self.lower_const_body(i.span, Some(x))), ), ), - AssocItemKind::Method(ref sig, None) => { + AssocItemKind::Fn(ref sig, None) => { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig( &i.generics, @@ -837,7 +837,7 @@ impl LoweringContext<'_> { ); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } - AssocItemKind::Method(ref sig, Some(ref body)) => { + AssocItemKind::Fn(ref sig, Some(ref body)) => { let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = self.lower_method_sig( &i.generics, @@ -880,7 +880,7 @@ impl LoweringContext<'_> { AssocItemKind::TyAlias(_, ref default) => { (hir::AssocItemKind::Type, default.is_some()) } - AssocItemKind::Method(ref sig, ref default) => ( + AssocItemKind::Fn(ref sig, ref default) => ( hir::AssocItemKind::Method { has_self: sig.decl.has_self(), }, @@ -913,7 +913,7 @@ impl LoweringContext<'_> { self.lower_const_body(i.span, expr.as_deref()), ), ), - AssocItemKind::Method(ref sig, ref body) => { + AssocItemKind::Fn(ref sig, ref body) => { self.current_item = Some(i.span); let body_id = self.lower_maybe_async_body( i.span, @@ -984,7 +984,7 @@ impl LoweringContext<'_> { None => hir::AssocItemKind::Type, Some(_) => hir::AssocItemKind::OpaqueTy, }, - AssocItemKind::Method(sig, _) => hir::AssocItemKind::Method { + AssocItemKind::Fn(sig, _) => hir::AssocItemKind::Method { has_self: sig.decl.has_self(), }, AssocItemKind::Macro(..) => unimplemented!(), diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index da8eae6028e36..e84ac82942c8e 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -779,7 +779,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn flat_map_trait_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { let is_const = match i.kind { ast::AssocItemKind::Const(..) => true, - ast::AssocItemKind::Method(ref sig, _) => Self::is_sig_const(sig), + ast::AssocItemKind::Fn(ref sig, _) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 8916fc0883871..1fc89961889f1 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -269,7 +269,7 @@ impl EarlyLintPass for UnsafeCode { } fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::AssocItem) { - if let ast::AssocItemKind::Method(ref sig, None) = item.kind { + if let ast::AssocItemKind::Fn(ref sig, None) = item.kind { if sig.header.unsafety == ast::Unsafety::Unsafe { self.report_unsafe(cx, item.span, "declaration of an `unsafe` method") } @@ -617,7 +617,7 @@ declare_lint_pass!( impl EarlyLintPass for AnonymousParameters { fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { match it.kind { - ast::AssocItemKind::Method(ref sig, _) => { + ast::AssocItemKind::Fn(ref sig, _) => { for arg in sig.decl.inputs.iter() { match arg.pat.kind { ast::PatKind::Ident(_, ident, None) => { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index a7c9888662280..0840a1551dbf4 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1790,7 +1790,7 @@ impl<'a> Parser<'a> { })?; let sig = FnSig { header, decl }; let body = self.parse_assoc_fn_body(at_end, attrs)?; - Ok((ident, AssocItemKind::Method(sig, body), generics)) + Ok((ident, AssocItemKind::Fn(sig, body), generics)) } /// Parse the "body" of a method in an associated item definition. diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 609885cb254b7..e90231f984b1f 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -544,7 +544,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } for impl_item in impl_items { self.invalid_visibility(&impl_item.vis, None); - if let AssocItemKind::Method(ref sig, _) = impl_item.kind { + if let AssocItemKind::Fn(ref sig, _) = impl_item.kind { self.check_trait_fn_not_const(sig.header.constness); self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node); } @@ -795,7 +795,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { AssocItemKind::Const(_, body) => { self.check_impl_item_provided(ii.span, body, "constant", " = ;"); } - AssocItemKind::Method(sig, body) => { + AssocItemKind::Fn(sig, body) => { self.check_impl_item_provided(ii.span, body, "function", " { }"); self.check_fn_decl(&sig.decl); } @@ -812,7 +812,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility(&ti.vis, None); self.check_defaultness(ti.span, ti.defaultness); - if let AssocItemKind::Method(sig, block) = &ti.kind { + if let AssocItemKind::Fn(sig, block) = &ti.kind { self.check_fn_decl(&sig.decl); self.check_trait_fn_not_async(ti.span, sig.header.asyncness.node); self.check_trait_fn_not_const(sig.header.constness); @@ -838,7 +838,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_assoc_item(&mut self, item: &'a AssocItem) { - if let AssocItemKind::Method(sig, _) = &item.kind { + if let AssocItemKind::Fn(sig, _) = &item.kind { self.check_c_varadic_type(&sig.decl); } visit::walk_assoc_item(self, item); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index dc3013754404b..e94e0dc695cd6 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1176,7 +1176,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let item_def_id = self.r.definitions.local_def_id(item.id); let (res, ns) = match item.kind { AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), - AssocItemKind::Method(ref sig, _) => { + AssocItemKind::Fn(ref sig, _) => { if sig.decl.has_self() { self.r.has_self.insert(item_def_id); } diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 6e26553d82f82..9bae339f80ea4 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -214,11 +214,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_trait_item(&mut self, ti: &'a AssocItem) { let def_data = match ti.kind { - AssocItemKind::Method(..) | AssocItemKind::Const(..) => - DefPathData::ValueNs(ti.ident.name), - AssocItemKind::TyAlias(..) => { - DefPathData::TypeNs(ti.ident.name) - }, + AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name), + AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ti.ident.name), AssocItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), }; @@ -228,7 +225,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a AssocItem) { let def_data = match ii.kind { - AssocItemKind::Method(FnSig { + AssocItemKind::Fn(FnSig { ref header, ref decl, }, ref body) if header.asyncness.node.is_async() => { @@ -242,7 +239,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { body.as_deref(), ) } - AssocItemKind::Method(..) | + AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name), AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name), AssocItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index ad29fd9e1db1e..ec9c2a5b75d83 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -818,7 +818,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { }); } } - AssocItemKind::Method(_, _) => { + AssocItemKind::Fn(_, _) => { visit::walk_assoc_item(this, trait_item) } AssocItemKind::TyAlias(..) => { @@ -1109,7 +1109,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { visit::walk_assoc_item(this, impl_item) }); } - AssocItemKind::Method(..) => { + AssocItemKind::Fn(..) => { // If this is a trait impl, ensure the method // exists in trait this.check_trait_item(impl_item.ident, diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 3b36c1c70f9f2..df6ad51d1045b 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1044,7 +1044,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &trait_item.attrs, ); } - ast::AssocItemKind::Method(ref sig, ref body) => { + ast::AssocItemKind::Fn(ref sig, ref body) => { self.process_method( sig, body.as_ref().map(|x| &**x), @@ -1115,7 +1115,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &impl_item.attrs, ); } - ast::AssocItemKind::Method(ref sig, ref body) => { + ast::AssocItemKind::Fn(ref sig, ref body) => { self.process_method( sig, body.as_deref(), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1b729ebaf4376..f7f84333857f6 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1634,8 +1634,7 @@ pub enum AssocItemKind { Const(P, Option>), /// An associated function. - /// FIXME(Centril): Rename to `Fn`. - Method(FnSig, Option>), + Fn(FnSig, Option>), /// An associated type. TyAlias(GenericBounds, Option>), diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index fcce9d4e95f5a..871ec2c008eee 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -573,7 +573,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_trait_item(&mut self, ti: &'a ast::AssocItem) { match ti.kind { - ast::AssocItemKind::Method(ref sig, ref block) => { + ast::AssocItemKind::Fn(ref sig, ref block) => { if block.is_none() { self.check_extern(sig.header.ext); } @@ -600,7 +600,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } match ii.kind { - ast::AssocItemKind::Method(ref sig, _) => { + ast::AssocItemKind::Fn(ref sig, _) => { if sig.decl.c_variadic() { gate_feature_post!( &self, c_variadic, ii.span, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 18d42f9dd668c..2a6cff5971c57 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -955,7 +955,7 @@ pub fn noop_flat_map_assoc_item(mut item: AssocItem, visitor: &mu visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } - AssocItemKind::Method(sig, body) => { + AssocItemKind::Fn(sig, body) => { visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9e4615f60c03c..87f6ae85b6970 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1528,7 +1528,7 @@ impl<'a> State<'a> { ast::AssocItemKind::Const(ty, expr) => { self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis); } - ast::AssocItemKind::Method(sig, body) => { + ast::AssocItemKind::Fn(sig, body) => { if body.is_some() { self.head(""); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index e2c0ee6146741..51e7fa1eb38b4 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -600,11 +600,11 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - AssocItemKind::Method(ref sig, None) => { + AssocItemKind::Fn(ref sig, None) => { visitor.visit_fn_header(&sig.header); walk_fn_decl(visitor, &sig.decl); } - AssocItemKind::Method(ref sig, Some(ref body)) => { + AssocItemKind::Fn(ref sig, Some(ref body)) => { visitor.visit_fn(FnKind::Method(item.ident, sig, &item.vis, body), &sig.decl, item.span, item.id); } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 1c1fcc4f301bc..b7707bfb8e5fb 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -958,7 +958,7 @@ impl<'a> MethodDef<'a> { vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, ident: method_ident, - kind: ast::AssocItemKind::Method(sig, Some(body_block)), + kind: ast::AssocItemKind::Fn(sig, Some(body_block)), tokens: None, } } From 74d4fbc5f5f68212d01a78738c207d5976fe13e4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Dec 2019 06:32:58 +0100 Subject: [PATCH 27/38] De-fatalize `...` parsing. Also fix error the code description. --- src/librustc_error_codes/error_codes/E0743.md | 16 +++++++++---- src/librustc_parse/parser/ty.rs | 16 +++++++------ .../variadic-ffi-nested-syntactic-fail.rs | 9 +++++++ .../variadic-ffi-nested-syntactic-fail.stderr | 24 +++++++++++++++++++ 4 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs create mode 100644 src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr diff --git a/src/librustc_error_codes/error_codes/E0743.md b/src/librustc_error_codes/error_codes/E0743.md index aaf19d8478ca2..1780fe59cbd69 100644 --- a/src/librustc_error_codes/error_codes/E0743.md +++ b/src/librustc_error_codes/error_codes/E0743.md @@ -1,11 +1,17 @@ -C-variadic has been used on a non-foreign function. +The C-variadic type `...` has been nested inside another type. Erroneous code example: ```compile_fail,E0743 -fn foo2(x: u8, ...) {} // error! +#![feature(c_variadic)] + +fn foo2(x: u8, y: &...) {} // error! ``` -Only foreign functions can use C-variadic (`...`). It is used to give an -undefined number of parameters to a given function (like `printf` in C). The -equivalent in Rust would be to use macros directly. +Only foreign functions can use the C-variadic type (`...`). +In such functions, `...` may only occur non-nested. +That is, `y: &'a ...` is not allowed. + +A C-variadic type is used to give an undefined number +of parameters to a given function (like `printf` in C). +The equivalent in Rust would be to use macros directly. diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 3ab290d1cbbc5..6f7ab0542d5fa 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -10,7 +10,7 @@ use syntax::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam use syntax::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef}; use syntax::ast::{Mutability, AnonConst, Mac}; use syntax::token::{self, Token}; -use syntax::struct_span_fatal; +use syntax::struct_span_err; use syntax_pos::source_map::Span; use syntax_pos::symbol::kw; @@ -209,19 +209,21 @@ impl<'a> Parser<'a> { TyKind::Path(None, path) } } - } else if self.check(&token::DotDotDot) { + } else if self.eat(&token::DotDotDot) { if allow_c_variadic { - self.eat(&token::DotDotDot); TyKind::CVarArgs } else { // FIXME(Centril): Should we just allow `...` syntactically // anywhere in a type and use semantic restrictions instead? - return Err(struct_span_fatal!( + struct_span_err!( self.sess.span_diagnostic, - self.token.span, + lo.to(self.prev_span), E0743, - "only foreign functions are allowed to be C-variadic", - )); + "C-variadic type `...` may not be nested inside another type", + ) + .emit(); + + TyKind::Err } } else { let msg = format!("expected type, found {}", self.this_token_descr()); diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs new file mode 100644 index 0000000000000..9eeee195e56e4 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs @@ -0,0 +1,9 @@ +fn f1<'a>(x: u8, y: &'a ...) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn f2<'a>(x: u8, y: Vec<&'a ...>) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr new file mode 100644 index 0000000000000..8b9d676a45dae --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr @@ -0,0 +1,24 @@ +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:1:25 + | +LL | fn f1<'a>(x: u8, y: &'a ...) {} + | ^^^ + +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:4:29 + | +LL | fn f2<'a>(x: u8, y: Vec<&'a ...>) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0743. +For more information about an error, try `rustc --explain E0308`. From 054458b48db87ce767d7cc3d2dd86846ada3e3da Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 11 Dec 2019 11:14:13 +0100 Subject: [PATCH 28/38] make visitor uses more robust --- src/librustc/hir/lowering/item.rs | 4 ++-- src/librustc_resolve/late.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index f0543b9057d1f..46c944fa67881 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -94,7 +94,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id); }); - visit::walk_assoc_item(self, item); + visit::walk_trait_item(self, item); } fn visit_impl_item(&mut self, item: &'tcx AssocItem) { @@ -104,7 +104,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { lctx.impl_items.insert(id, hir_item); lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id); }); - visit::walk_assoc_item(self, item); + visit::walk_impl_item(self, item); } } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index ec9c2a5b75d83..4321f62e03bc8 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -819,10 +819,10 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } } AssocItemKind::Fn(_, _) => { - visit::walk_assoc_item(this, trait_item) + visit::walk_trait_item(this, trait_item) } AssocItemKind::TyAlias(..) => { - visit::walk_assoc_item(this, trait_item) + visit::walk_trait_item(this, trait_item) } AssocItemKind::Macro(_) => { panic!("unexpanded macro in resolve!") @@ -1106,7 +1106,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ); this.with_constant_rib(|this| { - visit::walk_assoc_item(this, impl_item) + visit::walk_impl_item(this, impl_item) }); } AssocItemKind::Fn(..) => { @@ -1117,7 +1117,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { impl_item.span, |n, s| MethodNotMemberOfTrait(n, s)); - visit::walk_assoc_item(this, impl_item); + visit::walk_impl_item(this, impl_item); } AssocItemKind::TyAlias(_, Some(ref ty)) => { // If this is a trait impl, ensure the type From 2d8d8136fa4d67574e7b27a3f262819627cf1622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Wed, 4 Dec 2019 18:40:16 +0100 Subject: [PATCH 29/38] Update tokio crates to latest versions --- Cargo.lock | 152 +++++++++++++++++++---------------------------------- 1 file changed, 55 insertions(+), 97 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1af0442dde7fc..dd7a2147dd1cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -724,16 +724,6 @@ dependencies = [ "smallvec 0.6.10", ] -[[package]] -name = "crossbeam-deque" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils 0.6.5", -] - [[package]] name = "crossbeam-deque" version = "0.7.1" @@ -755,7 +745,7 @@ dependencies = [ "crossbeam-utils 0.6.5", "lazy_static 1.3.0", "memoffset", - "scopeguard 1.0.0", + "scopeguard", ] [[package]] @@ -1407,7 +1397,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3753954f7bd71f0e671afb8b5a992d1724cf43b7f95a563cd4a0bde94659ca8" dependencies = [ - "scopeguard 1.0.0", + "scopeguard", "winapi 0.3.8", ] @@ -1726,7 +1716,7 @@ dependencies = [ "jsonrpc-server-utils", "log", "parity-tokio-ipc", - "parking_lot 0.9.0", + "parking_lot", "tokio-service", ] @@ -1738,7 +1728,7 @@ checksum = "e2c08b444cc0ed70263798834343d0ac875e664257df8079160f23ac1ea79446" dependencies = [ "jsonrpc-core", "log", - "parking_lot 0.9.0", + "parking_lot", "serde", ] @@ -1850,23 +1840,13 @@ dependencies = [ name = "linkchecker" version = "0.1.0" -[[package]] -name = "lock_api" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" -dependencies = [ - "owning_ref", - "scopeguard 0.3.3", -] - [[package]] name = "lock_api" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" dependencies = [ - "scopeguard 1.0.0", + "scopeguard", ] [[package]] @@ -2027,7 +2007,7 @@ checksum = "c420bbc064623934620b5ab2dc0cf96451b34163329e82f95e7fa1b7b99a6ac8" dependencies = [ "byteorder", "memmap", - "parking_lot 0.9.0", + "parking_lot", "rustc-hash", ] @@ -2320,15 +2300,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024" -[[package]] -name = "owning_ref" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -dependencies = [ - "stable_deref_trait", -] - [[package]] name = "packed_simd" version = "0.3.1" @@ -2377,38 +2348,15 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "parking_lot" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -dependencies = [ - "lock_api 0.1.3", - "parking_lot_core 0.4.0", -] - [[package]] name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ - "lock_api 0.3.1", - "parking_lot_core 0.6.2", - "rustc_version", -] - -[[package]] -name = "parking_lot_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -dependencies = [ - "libc", - "rand 0.6.1", + "lock_api", + "parking_lot_core", "rustc_version", - "smallvec 0.6.10", - "winapi 0.3.8", ] [[package]] @@ -2879,7 +2827,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" dependencies = [ - "crossbeam-deque 0.7.1", + "crossbeam-deque", "either", "rayon-core", ] @@ -2890,7 +2838,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" dependencies = [ - "crossbeam-deque 0.7.1", + "crossbeam-deque", "crossbeam-queue", "crossbeam-utils 0.6.5", "lazy_static 1.3.0", @@ -3155,7 +3103,7 @@ dependencies = [ "log", "measureme", "num_cpus", - "parking_lot 0.9.0", + "parking_lot", "polonius-engine", "rustc-rayon", "rustc-rayon-core", @@ -3205,7 +3153,7 @@ dependencies = [ "jobserver", "lazy_static 1.3.0", "log", - "parking_lot 0.9.0", + "parking_lot", "rustc-ap-graphviz", "rustc-ap-rustc_index", "rustc-ap-serialize", @@ -3360,7 +3308,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" dependencies = [ - "crossbeam-deque 0.7.1", + "crossbeam-deque", "either", "rustc-rayon-core", ] @@ -3371,7 +3319,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2427831f0053ea3ea73559c8eabd893133a51b251d142bacee53c62a288cb3" dependencies = [ - "crossbeam-deque 0.7.1", + "crossbeam-deque", "crossbeam-queue", "crossbeam-utils 0.6.5", "lazy_static 1.3.0", @@ -3515,7 +3463,7 @@ dependencies = [ "lazy_static 1.3.0", "log", "measureme", - "parking_lot 0.9.0", + "parking_lot", "rustc-hash", "rustc-rayon", "rustc-rayon-core", @@ -4054,12 +4002,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" - [[package]] name = "scopeguard" version = "1.0.0" @@ -4655,9 +4597,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.1.14" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ "bytes", "futures", @@ -4669,6 +4611,7 @@ dependencies = [ "tokio-fs", "tokio-io", "tokio-reactor", + "tokio-sync", "tokio-tcp", "tokio-threadpool", "tokio-timer", @@ -4700,9 +4643,9 @@ dependencies = [ [[package]] name = "tokio-current-thread" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" +checksum = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" dependencies = [ "futures", "tokio-executor", @@ -4710,9 +4653,9 @@ dependencies = [ [[package]] name = "tokio-executor" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +checksum = "ca6df436c42b0c3330a82d855d2ef017cd793090ad550a6bc2184f4b933532ab" dependencies = [ "crossbeam-utils 0.6.5", "futures", @@ -4720,9 +4663,9 @@ dependencies = [ [[package]] name = "tokio-fs" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" +checksum = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" dependencies = [ "futures", "tokio-io", @@ -4731,9 +4674,9 @@ dependencies = [ [[package]] name = "tokio-io" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" +checksum = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" dependencies = [ "bytes", "futures", @@ -4755,12 +4698,15 @@ dependencies = [ [[package]] name = "tokio-process" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88e1281e412013f1ff5787def044a9577a0bed059f451e835f1643201f8b777d" +checksum = "afbd6ef1b8cc2bd2c2b580d882774d443ebb1c6ceefe35ba9ea4ab586c89dbe8" dependencies = [ + "crossbeam-queue", "futures", + "lazy_static 1.3.0", "libc", + "log", "mio", "mio-named-pipes", "tokio-io", @@ -4771,9 +4717,9 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" +checksum = "6732fe6b53c8d11178dcb77ac6d9682af27fc6d4cb87789449152e5377377146" dependencies = [ "crossbeam-utils 0.6.5", "futures", @@ -4781,10 +4727,11 @@ dependencies = [ "log", "mio", "num_cpus", - "parking_lot 0.7.1", + "parking_lot", "slab", "tokio-executor", "tokio-io", + "tokio-sync", ] [[package]] @@ -4813,6 +4760,16 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "tokio-sync" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" +dependencies = [ + "fnv", + "futures", +] + [[package]] name = "tokio-tcp" version = "0.1.3" @@ -4829,25 +4786,26 @@ dependencies = [ [[package]] name = "tokio-threadpool" -version = "0.1.10" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa" +checksum = "f0c32ffea4827978e9aa392d2f743d973c1dfa3730a2ed3f22ce1e6984da848c" dependencies = [ - "crossbeam-channel", - "crossbeam-deque 0.6.3", + "crossbeam-deque", + "crossbeam-queue", "crossbeam-utils 0.6.5", "futures", + "lazy_static 1.3.0", "log", "num_cpus", - "rand 0.6.1", + "slab", "tokio-executor", ] [[package]] name = "tokio-timer" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +checksum = "1739638e364e558128461fc1ad84d997702c8e31c2e6b18fb99842268199e827" dependencies = [ "crossbeam-utils 0.6.5", "futures", @@ -4857,9 +4815,9 @@ dependencies = [ [[package]] name = "tokio-udp" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +checksum = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" dependencies = [ "bytes", "futures", From aa0ef5a01ff329daa822e7443ca7d6ae2bfc8476 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 16 Dec 2019 14:15:57 -0800 Subject: [PATCH 30/38] Fix handling of wasm import modules and names The WebAssembly targets of rustc have weird issues around name mangling and import the same name from different modules. This all largely stems from the fact that we're using literal symbol names in LLVM IR to represent what a function is called when it's imported, and we're not using the wasm-specific `wasm-import-name` attribute. This in turn leads to two issues: * If, in the same codegen unit, the same FFI symbol is referenced twice then rustc, when translating to LLVM IR, will only reference one symbol from the first wasm module referenced. * There's also a bug in LLD [1] where even if two codegen units reference different modules, having the same symbol names means that LLD coalesces the symbols and only refers to one wasm module. Put another way, all our imported wasm symbols from the environment are keyed off their LLVM IR symbol name, which has lots of collisions today. This commit fixes the issue by implementing two changes: 1. All wasm symbols with `#[link(wasm_import_module = "...")]` are mangled by default in LLVM IR. This means they're all given unique names. 2. Symbols then use the `wasm-import-name` attribute to ensure that the WebAssembly file uses the correct import name. When put together this should ensure we don't trip over the LLD bug [1] and we also codegen IR correctly always referencing the right symbols with the right import module/name pairs. Closes #50021 Closes #56309 Closes #63562 [1]: https://bugs.llvm.org/show_bug.cgi?id=44316 --- src/librustc_codegen_llvm/attributes.rs | 11 +++++++ src/librustc_codegen_utils/symbol_names.rs | 28 +++++++++++++--- .../wasm-symbols-different-module/Makefile | 28 ++++++++++++++++ .../wasm-symbols-different-module/bar.rs | 33 +++++++++++++++++++ .../wasm-symbols-different-module/baz.rs | 22 +++++++++++++ .../wasm-symbols-different-module/foo.rs | 23 +++++++++++++ .../wasm-symbols-different-module/log.rs | 16 +++++++++ .../verify-imports.js | 32 ++++++++++++++++++ 8 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 src/test/run-make/wasm-symbols-different-module/Makefile create mode 100644 src/test/run-make/wasm-symbols-different-module/bar.rs create mode 100644 src/test/run-make/wasm-symbols-different-module/baz.rs create mode 100644 src/test/run-make/wasm-symbols-different-module/foo.rs create mode 100644 src/test/run-make/wasm-symbols-different-module/log.rs create mode 100644 src/test/run-make/wasm-symbols-different-module/verify-imports.js diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 1ea9362dc4260..6779cce1f8a56 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -343,6 +343,17 @@ pub fn from_fn_attrs( const_cstr!("wasm-import-module"), &module, ); + + let name = codegen_fn_attrs.link_name.unwrap_or_else(|| { + cx.tcx.item_name(instance.def_id()) + }); + let name = CString::new(&name.as_str()[..]).unwrap(); + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + const_cstr!("wasm-import-name"), + &name, + ); } } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index c52c6cfa83c91..922964ee45f6b 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -142,12 +142,32 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { }; let attrs = tcx.codegen_fn_attrs(def_id); + + // Foreign items by default use no mangling for their symbol name. There's a + // few exceptions to this rule though: + // + // * This can be overridden with the `#[link_name]` attribute + // + // * On the wasm32 targets there is a bug (or feature) in LLD [1] where the + // same-named symbol when imported from different wasm modules will get + // hooked up incorectly. As a result foreign symbols, on the wasm target, + // with a wasm import module, get mangled. Additionally our codegen will + // deduplicate symbols based purely on the symbol name, but for wasm this + // isn't quite right because the same-named symbol on wasm can come from + // different modules. For these reasons if `#[link(wasm_import_module)]` + // is present we mangle everything on wasm because the demangled form will + // show up in the `wasm-import-name` custom attribute in LLVM IR. + // + // [1]: https://bugs.llvm.org/show_bug.cgi?id=44316 if is_foreign { - if let Some(name) = attrs.link_name { - return name; + if tcx.sess.target.target.arch != "wasm32" || + !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id) + { + if let Some(name) = attrs.link_name { + return name; + } + return tcx.item_name(def_id); } - // Don't mangle foreign items. - return tcx.item_name(def_id); } if let Some(name) = attrs.export_name { diff --git a/src/test/run-make/wasm-symbols-different-module/Makefile b/src/test/run-make/wasm-symbols-different-module/Makefile new file mode 100644 index 0000000000000..bb6a5d3c9d24a --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/Makefile @@ -0,0 +1,28 @@ +-include ../../run-make-fulldeps/tools.mk + +# only-wasm32-bare + +all: + $(RUSTC) foo.rs --target wasm32-unknown-unknown + $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo + $(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto + $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo + $(RUSTC) foo.rs --target wasm32-unknown-unknown -O + $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo + $(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto + $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo + + $(RUSTC) bar.rs --target wasm32-unknown-unknown + $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f + $(RUSTC) bar.rs --target wasm32-unknown-unknown -C lto + $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f + $(RUSTC) bar.rs --target wasm32-unknown-unknown -O + $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f + $(RUSTC) bar.rs --target wasm32-unknown-unknown -O -C lto + $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f + + $(RUSTC) baz.rs --target wasm32-unknown-unknown + $(NODE) verify-imports.js $(TMPDIR)/baz.wasm sqlite/allocate sqlite/deallocate + + $(RUSTC) log.rs --target wasm32-unknown-unknown + $(NODE) verify-imports.js $(TMPDIR)/log.wasm test/log diff --git a/src/test/run-make/wasm-symbols-different-module/bar.rs b/src/test/run-make/wasm-symbols-different-module/bar.rs new file mode 100644 index 0000000000000..7567060d7813a --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/bar.rs @@ -0,0 +1,33 @@ +//! Issue #50021 + +#![crate_type = "cdylib"] + +mod m1 { + #[link(wasm_import_module = "m1")] + extern "C" { + pub fn f(); + } + #[link(wasm_import_module = "m1")] + extern "C" { + pub fn g(); + } +} + +mod m2 { + #[link(wasm_import_module = "m2")] + extern "C" { + pub fn f(_: i32); + } +} + +#[no_mangle] +pub unsafe fn run() { + m1::f(); + m1::g(); + + // In generated code, expected: + // (import "m2" "f" (func $f (param i32))) + // but got: + // (import "m1" "f" (func $f (param i32))) + m2::f(0); +} diff --git a/src/test/run-make/wasm-symbols-different-module/baz.rs b/src/test/run-make/wasm-symbols-different-module/baz.rs new file mode 100644 index 0000000000000..fbb78619bb8f5 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/baz.rs @@ -0,0 +1,22 @@ +//! Issue #63562 + +#![crate_type = "cdylib"] + +mod foo { + #[link(wasm_import_module = "sqlite")] + extern "C" { + pub fn allocate(size: usize) -> i32; + pub fn deallocate(ptr: i32, size: usize); + } +} + +#[no_mangle] +pub extern "C" fn allocate() { + unsafe { + foo::allocate(1); + foo::deallocate(1, 2); + } +} + +#[no_mangle] +pub extern "C" fn deallocate() {} diff --git a/src/test/run-make/wasm-symbols-different-module/foo.rs b/src/test/run-make/wasm-symbols-different-module/foo.rs new file mode 100644 index 0000000000000..a4ba7e714cc77 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/foo.rs @@ -0,0 +1,23 @@ +#![crate_type = "cdylib"] + +mod a { + #[link(wasm_import_module = "a")] + extern "C" { + pub fn foo(); + } +} + +mod b { + #[link(wasm_import_module = "b")] + extern "C" { + pub fn foo(); + } +} + +#[no_mangle] +pub fn start() { + unsafe { + a::foo(); + b::foo(); + } +} diff --git a/src/test/run-make/wasm-symbols-different-module/log.rs b/src/test/run-make/wasm-symbols-different-module/log.rs new file mode 100644 index 0000000000000..ea3e0b4b2be91 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/log.rs @@ -0,0 +1,16 @@ +//! Issue #56309 + +#![crate_type = "cdylib"] + +#[link(wasm_import_module = "test")] +extern "C" { + fn log(message_data: u32, message_size: u32); +} + +#[no_mangle] +pub fn main() { + let message = "Hello, world!"; + unsafe { + log(message.as_ptr() as u32, message.len() as u32); + } +} diff --git a/src/test/run-make/wasm-symbols-different-module/verify-imports.js b/src/test/run-make/wasm-symbols-different-module/verify-imports.js new file mode 100644 index 0000000000000..7e9f90cf8bdc6 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/verify-imports.js @@ -0,0 +1,32 @@ +const fs = require('fs'); +const process = require('process'); +const assert = require('assert'); +const buffer = fs.readFileSync(process.argv[2]); + +let m = new WebAssembly.Module(buffer); +let list = WebAssembly.Module.imports(m); +console.log('imports', list); +if (list.length !== process.argv.length - 3) + throw new Error("wrong number of imports") + +const imports = new Map(); +for (let i = 3; i < process.argv.length; i++) { + const [module, name] = process.argv[i].split('/'); + if (!imports.has(module)) + imports.set(module, new Map()); + imports.get(module).set(name, true); +} + +for (let i of list) { + if (imports.get(i.module) === undefined || imports.get(i.module).get(i.name) === undefined) + throw new Error(`didn't find import of ${i.module}::${i.name}`); + imports.get(i.module).delete(i.name); + + if (imports.get(i.module).size === 0) + imports.delete(i.module); +} + +console.log(imports); +if (imports.size !== 0) { + throw new Error('extra imports'); +} From 3a19fbf95d3b289f4c17aba910051cd9afd75887 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 23 Dec 2018 19:00:58 +0000 Subject: [PATCH 31/38] Add Rvalue::AddressOf to MIR This operator creates a raw pointer to a Place directly, without first creating a reference. See RFC #2582 for motivation. The Rvalue is currently unused. --- src/librustc/mir/mod.rs | 18 +++ src/librustc/mir/tcx.rs | 7 ++ src/librustc/mir/visit.rs | 16 +++ src/librustc/ty/cast.rs | 3 - src/librustc_codegen_ssa/mir/analyze.rs | 2 + src/librustc_codegen_ssa/mir/place.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 58 +++++---- src/librustc_mir/borrow_check/invalidation.rs | 18 ++- src/librustc_mir/borrow_check/mod.rs | 25 ++++ .../borrow_check/type_check/mod.rs | 49 ++------ .../dataflow/move_paths/builder.rs | 1 + src/librustc_mir/interpret/step.rs | 2 +- src/librustc_mir/transform/add_retag.rs | 18 +-- .../transform/check_consts/ops.rs | 17 +++ .../transform/check_consts/qualifs.rs | 18 ++- .../transform/check_consts/validation.rs | 112 +++++++++++------- src/librustc_mir/transform/promote_consts.rs | 24 +++- .../transform/qualify_min_const_fn.rs | 8 +- src/librustc_mir/util/liveness.rs | 2 + src/librustc_typeck/check/cast.rs | 76 ++++++------ 20 files changed, 307 insertions(+), 169 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ba8feb4ee739d..3b4adbaf78c74 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2060,6 +2060,11 @@ pub enum Rvalue<'tcx> { /// &x or &mut x Ref(Region<'tcx>, BorrowKind, Place<'tcx>), + /// Create a raw pointer to the given place + /// Can be generated by raw address of expressions (`&raw const x`), + /// or when casting a reference to a raw pointer. + AddressOf(Mutability, Place<'tcx>), + /// length of a [X] or [X;n] value Len(Place<'tcx>), @@ -2214,6 +2219,15 @@ impl<'tcx> Debug for Rvalue<'tcx> { write!(fmt, "&{}{}{:?}", region, kind_str, place) } + AddressOf(mutability, ref place) => { + let kind_str = match mutability { + Mutability::Mut => "mut", + Mutability::Not => "const", + }; + + write!(fmt, "&raw {} {:?}", kind_str, place) + } + Aggregate(ref kind, ref places) => { fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result { let mut tuple_fmt = fmt.debug_tuple(""); @@ -3085,6 +3099,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Ref(region, bk, ref place) => { Ref(region.fold_with(folder), bk, place.fold_with(folder)) } + AddressOf(mutability, ref place) => { + AddressOf(mutability, place.fold_with(folder)) + } Len(ref place) => Len(place.fold_with(folder)), Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), BinaryOp(op, ref rhs, ref lhs) => { @@ -3125,6 +3142,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Use(ref op) => op.visit_with(visitor), Repeat(ref op, _) => op.visit_with(visitor), Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor), + AddressOf(_, ref place) => place.visit_with(visitor), Len(ref place) => place.visit_with(visitor), Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor), BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => { diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 445fa6ea8cab3..a24b1d863d644 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -172,6 +172,13 @@ impl<'tcx> Rvalue<'tcx> { } ) } + Rvalue::AddressOf(mutability, ref place) => { + let place_ty = place.ty(local_decls, tcx).ty; + tcx.mk_ptr(ty::TypeAndMut { + ty: place_ty, + mutbl: mutability.into(), + }) + } Rvalue::Len(..) => tcx.types.usize, Rvalue::Cast(.., ty) => ty, Rvalue::BinaryOp(op, ref lhs, ref rhs) => { diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 5d273fe85b6d2..fa96b51347d35 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -570,6 +570,18 @@ macro_rules! make_mir_visitor { self.visit_place(path, ctx, location); } + Rvalue::AddressOf(m, path) => { + let ctx = match m { + Mutability::Mut => PlaceContext::MutatingUse( + MutatingUseContext::AddressOf + ), + Mutability::Not => PlaceContext::NonMutatingUse( + NonMutatingUseContext::AddressOf + ), + }; + self.visit_place(path, ctx, location); + } + Rvalue::Len(path) => { self.visit_place( path, @@ -1031,6 +1043,8 @@ pub enum NonMutatingUseContext { ShallowBorrow, /// Unique borrow. UniqueBorrow, + /// AddressOf for *const pointer. + AddressOf, /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place. /// For example, the projection `x.y` is not marked as a mutation in these cases: /// @@ -1054,6 +1068,8 @@ pub enum MutatingUseContext { Drop, /// Mutable borrow. Borrow, + /// AddressOf for *mut pointer. + AddressOf, /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place. /// For example, the projection `x.y` is marked as a mutation in these cases: /// diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs index bc12412312deb..fca53db1475a0 100644 --- a/src/librustc/ty/cast.rs +++ b/src/librustc/ty/cast.rs @@ -28,8 +28,6 @@ pub enum CastTy<'tcx> { FnPtr, /// Raw pointers Ptr(ty::TypeAndMut<'tcx>), - /// References - RPtr(ty::TypeAndMut<'tcx>), } /// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs) @@ -63,7 +61,6 @@ impl<'tcx> CastTy<'tcx> { ty::Adt(d,_) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)), ty::RawPtr(mt) => Some(CastTy::Ptr(mt)), - ty::Ref(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })), ty::FnPtr(..) => Some(CastTy::FnPtr), _ => None, } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 6c627085b2ed8..7bcd981678640 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -340,10 +340,12 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> PlaceContext::MutatingUse(MutatingUseContext::Store) | PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) | + PlaceContext::MutatingUse(MutatingUseContext::AddressOf) | PlaceContext::MutatingUse(MutatingUseContext::Projection) | PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => { self.not_ssa(local); } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 5e13cabced000..5b21dfbdf1c69 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -448,7 +448,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cx = self.cx; let tcx = self.cx.tcx(); - let result = match &place_ref { + let result = match place_ref { mir::PlaceRef { base: mir::PlaceBase::Local(index), projection: [], diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 488ae8dbf9036..3a8d782aa7308 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -7,7 +7,7 @@ use crate::MemFlags; use crate::common::{self, RealPredicate, IntPredicate}; use crate::traits::*; -use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance}; +use rustc::ty::{self, Ty, TyCtxt, adjustment::{PointerCast}, Instance}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; use rustc::mir; @@ -342,8 +342,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } (CastTy::Ptr(_), CastTy::Ptr(_)) | - (CastTy::FnPtr, CastTy::Ptr(_)) | - (CastTy::RPtr(_), CastTy::Ptr(_)) => + (CastTy::FnPtr, CastTy::Ptr(_)) => bx.pointercast(llval, ll_t_out), (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => @@ -370,24 +369,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Ref(_, bk, ref place) => { - let cg_place = self.codegen_place(&mut bx, &place.as_ref()); - - let ty = cg_place.layout.ty; + let mk_ref = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ref( + tcx.lifetimes.re_erased, + ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() } + ); + self.codegen_place_to_pointer(bx, place, mk_ref) + } - // Note: places are indirect, so storing the `llval` into the - // destination effectively creates a reference. - let val = if !bx.cx().type_has_metadata(ty) { - OperandValue::Immediate(cg_place.llval) - } else { - OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap()) - }; - (bx, OperandRef { - val, - layout: self.cx.layout_of(self.cx.tcx().mk_ref( - self.cx.tcx().lifetimes.re_erased, - ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() } - )), - }) + mir::Rvalue::AddressOf(mutability, ref place) => { + let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ptr( + ty::TypeAndMut { ty, mutbl: mutability.into() } + ); + self.codegen_place_to_pointer(bx, place, mk_ptr) } mir::Rvalue::Len(ref place) => { @@ -543,6 +536,30 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_value.len(bx.cx()) } + /// Codegen an `Rvalue::AddressOf` or `Rvalue::Ref` + fn codegen_place_to_pointer( + &mut self, + mut bx: Bx, + place: &mir::Place<'tcx>, + mk_ptr_ty: impl FnOnce(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>, + ) -> (Bx, OperandRef<'tcx, Bx::Value>) { + let cg_place = self.codegen_place(&mut bx, &place.as_ref()); + + let ty = cg_place.layout.ty; + + // Note: places are indirect, so storing the `llval` into the + // destination effectively creates a reference. + let val = if !bx.cx().type_has_metadata(ty) { + OperandValue::Immediate(cg_place.llval) + } else { + OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap()) + }; + (bx, OperandRef { + val, + layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)), + }) + } + pub fn codegen_scalar_binop( &mut self, bx: &mut Bx, @@ -699,6 +716,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { match *rvalue { mir::Rvalue::Ref(..) | + mir::Rvalue::AddressOf(..) | mir::Rvalue::Len(..) | mir::Rvalue::Cast(..) | // (*) mir::Rvalue::BinaryOp(..) | diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 58fac5512d9b6..d5b9aaf9511a1 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -3,7 +3,7 @@ use rustc::mir::visit::Visitor; use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyAndCache, Rvalue}; use rustc::mir::{Statement, StatementKind}; use rustc::mir::TerminatorKind; -use rustc::mir::{Operand, BorrowKind}; +use rustc::mir::{Operand, BorrowKind, Mutability}; use rustc_data_structures::graph::dominators::Dominators; use crate::dataflow::indexes::BorrowIndex; @@ -337,6 +337,22 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { ); } + Rvalue::AddressOf(mutability, ref place) => { + let access_kind = match mutability { + Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut { + allow_two_phase_borrow: false, + }))), + Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), + }; + + self.access_place( + location, + place, + access_kind, + LocalMutationIsAllowed::No, + ); + } + Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 11012ef2fc7ee..2554d5e729da9 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1233,6 +1233,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } + + Rvalue::AddressOf(mutability, ref place) => { + let access_kind = match mutability { + Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut { + allow_two_phase_borrow: false, + }))), + Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), + }; + + self.access_place( + location, + (place, span), + access_kind, + LocalMutationIsAllowed::No, + flow_state, + ); + + self.check_if_path_or_subpath_is_moved( + location, + InitializationRequiringAction::Borrow, + (place.as_ref(), span), + flow_state, + ); + } + Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 663536bc2b4b6..108279eeef492 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -2273,41 +2273,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(ty); match (cast_ty_from, cast_ty_to) { - (Some(CastTy::RPtr(ref_tm)), Some(CastTy::Ptr(ptr_tm))) => { - if let hir::Mutability::Mutable = ptr_tm.mutbl { - if let Err(terr) = self.eq_types( - ref_tm.ty, - ptr_tm.ty, - location.to_locations(), - ConstraintCategory::Cast, - ) { - span_mirbug!( - self, - rvalue, - "equating {:?} with {:?} yields {:?}", - ref_tm.ty, - ptr_tm.ty, - terr - ) - } - } else { - if let Err(terr) = self.sub_types( - ref_tm.ty, - ptr_tm.ty, - location.to_locations(), - ConstraintCategory::Cast, - ) { - span_mirbug!( - self, - rvalue, - "relating {:?} with {:?} yields {:?}", - ref_tm.ty, - ptr_tm.ty, - terr - ) - } - } - }, (None, _) | (_, None) | (_, Some(CastTy::FnPtr)) @@ -2320,7 +2285,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty_from, ty, ), - _ => (), + (Some(CastTy::Int(_)), Some(CastTy::Int(_))) + | (Some(CastTy::Float), Some(CastTy::Int(_))) + | (Some(CastTy::Int(_)), Some(CastTy::Float)) + | (Some(CastTy::Float), Some(CastTy::Float)) + | (Some(CastTy::Ptr(_)), Some(CastTy::Int(_))) + | (Some(CastTy::FnPtr), Some(CastTy::Int(_))) + | (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) + | (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) + | (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (), } } } @@ -2371,7 +2344,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - Rvalue::Use(..) + Rvalue::AddressOf(..) + | Rvalue::Use(..) | Rvalue::Len(..) | Rvalue::BinaryOp(..) | Rvalue::CheckedBinaryOp(..) @@ -2388,6 +2362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::Use(_) | Rvalue::Repeat(..) | Rvalue::Ref(..) + | Rvalue::AddressOf(..) | Rvalue::Len(..) | Rvalue::Cast(..) | Rvalue::BinaryOp(..) diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index fa0864e0de760..5522da6fbf085 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -335,6 +335,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } } Rvalue::Ref(..) + | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) | Rvalue::NullaryOp(NullOp::SizeOf, _) diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 33ed69af6ba02..33cdf1b27f8db 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -248,7 +248,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )?; } - Ref(_, _, ref place) => { + AddressOf(_, ref place) | Ref(_, _, ref place) => { let src = self.eval_place(place)?; let place = self.force_allocation(src)?; if place.layout.size.bytes() > 0 { diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index dc21c674eea2f..0e4fe3f7f4015 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -136,21 +136,9 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // iterate backwards using indices. for i in (0..block_data.statements.len()).rev() { let (retag_kind, place) = match block_data.statements[i].kind { - // If we are casting *from* a reference, we may have to retag-as-raw. - StatementKind::Assign(box(ref place, Rvalue::Cast( - CastKind::Misc, - ref src, - dest_ty, - ))) => { - let src_ty = src.ty(&*local_decls, tcx); - if src_ty.is_region_ptr() { - // The only `Misc` casts on references are those creating raw pointers. - assert!(dest_ty.is_unsafe_ptr()); - (RetagKind::Raw, place.clone()) - } else { - // Some other cast, no retag - continue - } + // Retag-as-raw after escaping to a raw pointer. + StatementKind::Assign(box (ref place, Rvalue::AddressOf(..))) => { + (RetagKind::Raw, place.clone()) } // Assignments of reference or ptr type are the ones where we may have // to update tags. This includes `x = &[mut] ...` and hence diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 3df60993d9ad5..e5f3003cd7110 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -224,6 +224,23 @@ impl NonConstOp for MutBorrow { } } +#[derive(Debug)] +pub struct MutAddressOf; +impl NonConstOp for MutAddressOf { + fn feature_gate(tcx: TyCtxt<'_>) -> Option { + Some(tcx.features().const_mut_refs) + } + + fn emit_error(&self, item: &Item<'_, '_>, span: Span) { + feature_err( + &item.tcx.sess.parse_sess, + sym::const_mut_refs, + span, + &format!("`&raw mut` is not allowed in {}s", item.const_kind()) + ).emit(); + } +} + #[derive(Debug)] pub struct MutDeref; impl NonConstOp for MutDeref { diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 223a5f8d605fc..28243bd71a228 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -151,17 +151,15 @@ pub trait Qualif { Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs) } - Rvalue::Ref(_, _, ref place) => { + Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => { // Special-case reborrows to be more like a copy of the reference. - if let &[ref proj_base @ .., elem] = place.projection.as_ref() { - if ProjectionElem::Deref == elem { - let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty; - if let ty::Ref(..) = base_ty.kind { - return Self::in_place(cx, per_local, PlaceRef { - base: &place.base, - projection: proj_base, - }); - } + if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { + let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty; + if let ty::Ref(..) = base_ty.kind { + return Self::in_place(cx, per_local, PlaceRef { + base: &place.base, + projection: proj_base, + }); } } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 6261315c711cd..0904264586c7c 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -276,6 +276,27 @@ impl Validator<'a, 'mir, 'tcx> { self.check_op_spanned(ops::StaticAccess, span) } } + + fn check_immutable_borrow_like( + &mut self, + location: Location, + place: &Place<'tcx>, + ) { + // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually + // seek the cursors beforehand. + self.qualifs.has_mut_interior.cursor.seek_before(location); + self.qualifs.indirectly_mutable.seek(location); + + let borrowed_place_has_mut_interior = HasMutInterior::in_place( + &self.item, + &|local| self.qualifs.has_mut_interior_eager_seek(local), + place.as_ref(), + ); + + if borrowed_place_has_mut_interior { + self.check_op(ops::CellBorrow); + } + } } impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { @@ -302,26 +323,44 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location); // Special-case reborrows to be more like a copy of a reference. - if let Rvalue::Ref(_, kind, ref place) = *rvalue { - if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { - let ctx = match kind { - BorrowKind::Shared => PlaceContext::NonMutatingUse( - NonMutatingUseContext::SharedBorrow, - ), - BorrowKind::Shallow => PlaceContext::NonMutatingUse( - NonMutatingUseContext::ShallowBorrow, - ), - BorrowKind::Unique => PlaceContext::NonMutatingUse( - NonMutatingUseContext::UniqueBorrow, - ), - BorrowKind::Mut { .. } => PlaceContext::MutatingUse( - MutatingUseContext::Borrow, - ), - }; - self.visit_place_base(&place.base, ctx, location); - self.visit_projection(&place.base, reborrowed_proj, ctx, location); - return; + match *rvalue { + Rvalue::Ref(_, kind, ref place) => { + if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { + let ctx = match kind { + BorrowKind::Shared => PlaceContext::NonMutatingUse( + NonMutatingUseContext::SharedBorrow, + ), + BorrowKind::Shallow => PlaceContext::NonMutatingUse( + NonMutatingUseContext::ShallowBorrow, + ), + BorrowKind::Unique => PlaceContext::NonMutatingUse( + NonMutatingUseContext::UniqueBorrow, + ), + BorrowKind::Mut { .. } => PlaceContext::MutatingUse( + MutatingUseContext::Borrow, + ), + }; + self.visit_place_base(&place.base, ctx, location); + self.visit_projection(&place.base, reborrowed_proj, ctx, location); + return; + } } + Rvalue::AddressOf(mutbl, ref place) => { + if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { + let ctx = match mutbl { + Mutability::Not => PlaceContext::NonMutatingUse( + NonMutatingUseContext::AddressOf, + ), + Mutability::Mut => PlaceContext::MutatingUse( + MutatingUseContext::AddressOf, + ), + }; + self.visit_place_base(&place.base, ctx, location); + self.visit_projection(&place.base, reborrowed_proj, ctx, location); + return; + } + } + _ => {} } self.super_rvalue(rvalue, location); @@ -367,34 +406,25 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } } + Rvalue::AddressOf(Mutability::Mut, _) => { + self.check_op(ops::MutAddressOf) + } + // At the moment, `PlaceBase::Static` is only used for promoted MIR. | Rvalue::Ref(_, BorrowKind::Shared, ref place) | Rvalue::Ref(_, BorrowKind::Shallow, ref place) + | Rvalue::AddressOf(Mutability::Not, ref place) if matches!(place.base, PlaceBase::Static(_)) => bug!("Saw a promoted during const-checking, which must run before promotion"), - | Rvalue::Ref(_, kind @ BorrowKind::Shared, ref place) - | Rvalue::Ref(_, kind @ BorrowKind::Shallow, ref place) - => { - // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually - // seek the cursors beforehand. - self.qualifs.has_mut_interior.cursor.seek_before(location); - self.qualifs.indirectly_mutable.seek(location); - - let borrowed_place_has_mut_interior = HasMutInterior::in_place( - &self.item, - &|local| self.qualifs.has_mut_interior_eager_seek(local), - place.as_ref(), - ); - - if borrowed_place_has_mut_interior { - if let BorrowKind::Mut{ .. } = kind { - self.check_op(ops::MutBorrow); - } else { - self.check_op(ops::CellBorrow); - } - } - } + | Rvalue::Ref(_, BorrowKind::Shared, ref place) + | Rvalue::Ref(_, BorrowKind::Shallow, ref place) => { + self.check_immutable_borrow_like(location, place) + }, + + Rvalue::AddressOf(Mutability::Not, ref place) => { + self.check_immutable_borrow_like(location, place) + }, Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => { let operand_ty = operand.ty(*self.body, self.tcx); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 4c723199102be..4e5d8ae08fe5b 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -196,7 +196,12 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { } else if let TempState::Defined { ref mut uses, .. } = *temp { // We always allow borrows, even mutable ones, as we need // to promote mutable borrows of some ZSTs e.g., `&mut []`. - let allowed_use = context.is_borrow() || context.is_nonmutating_use(); + let allowed_use = match context { + PlaceContext::MutatingUse(MutatingUseContext::Borrow) + | PlaceContext::NonMutatingUse(_) => true, + PlaceContext::MutatingUse(_) + | PlaceContext::NonUse(_) => false, + }; debug!("visit_local: allowed_use={:?}", allowed_use); if allowed_use { *uses += 1; @@ -618,6 +623,21 @@ impl<'tcx> Validator<'_, 'tcx> { self.validate_operand(rhs) } + Rvalue::AddressOf(_, place) => { + // Raw reborrows can come from reference to pointer coercions, + // so are allowed. + if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { + let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty; + if let ty::Ref(..) = base_ty.kind { + return self.validate_place(PlaceRef { + base: &place.base, + projection: proj_base, + }); + } + } + Err(Unpromotable) + } + Rvalue::Ref(_, kind, place) => { if let BorrowKind::Mut { .. } = kind { let ty = place.ty(*self.body, self.tcx).ty; @@ -950,7 +970,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Candidate::Ref(loc) => { let ref mut statement = blocks[loc.block].statements[loc.statement_index]; match statement.kind { - StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref mut place))) => { + StatementKind::Assign(box (_, Rvalue::Ref(_, _, ref mut place))) => { // Use the underlying local for this (necessarily interior) borrow. let ty = place.base.ty(local_decls).ty; let span = statement.source_info.span; diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index e2530795749a9..a61bff37fc873 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -135,7 +135,10 @@ fn check_rvalue( Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { check_operand(tcx, operand, span, def_id, body) } - Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { + Rvalue::Len(place) + | Rvalue::Discriminant(place) + | Rvalue::Ref(_, _, place) + | Rvalue::AddressOf(_, place) => { check_place(tcx, place, span, def_id, body) } Rvalue::Cast(CastKind::Misc, operand, cast_ty) => { @@ -147,9 +150,6 @@ fn check_rvalue( span, "casting pointers to ints is unstable in const fn".into(), )), - (CastTy::RPtr(_), CastTy::Float) => bug!(), - (CastTy::RPtr(_), CastTy::Int(_)) => bug!(), - (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(), _ => check_operand(tcx, operand, span, def_id, body), } } diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 68c2e16399a59..01eebeb8c55a5 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -167,6 +167,8 @@ pub fn categorize(context: PlaceContext) -> Option { PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) | + PlaceContext::MutatingUse(MutatingUseContext::AddressOf) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) | diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 035ece238104f..21ba02746c79e 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -469,22 +469,48 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { - if let ty::FnDef(..) = self.expr_ty.kind { - // Attempt a coercion to a fn pointer type. - let f = self.expr_ty.fn_sig(fcx.tcx); - let res = fcx.try_coerce(self.expr, - self.expr_ty, - fcx.tcx.mk_fn_ptr(f), - AllowTwoPhase::No); - if let Err(TypeError::IntrinsicCast) = res { - return Err(CastError::IllegalCast); + match self.expr_ty.kind { + ty::FnDef(..) => { + // Attempt a coercion to a fn pointer type. + let f = self.expr_ty.fn_sig(fcx.tcx); + let res = fcx.try_coerce(self.expr, + self.expr_ty, + fcx.tcx.mk_fn_ptr(f), + AllowTwoPhase::No); + if let Err(TypeError::IntrinsicCast) = res { + return Err(CastError::IllegalCast); + } + if res.is_err() { + return Err(CastError::NonScalar); + } + (FnPtr, t_cast) } - if res.is_err() { - return Err(CastError::NonScalar); + // Special case some errors for references, and check for + // array-ptr-casts. `Ref` is not a CastTy because the cast + // is split into a coercion to a pointer type, followed by + // a cast. + ty::Ref(_, inner_ty, mutbl) => { + return match t_cast { + Int(_) | Float => match inner_ty.kind { + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Infer(ty::InferTy::IntVar(_)) | + ty::Infer(ty::InferTy::FloatVar(_)) => { + Err(CastError::NeedDeref) + } + _ => Err(CastError::NeedViaPtr), + } + // array-ptr-cast + Ptr(mt) => self.check_ref_cast( + fcx, + TypeAndMut { mutbl, ty: inner_ty }, + mt, + ), + _ => Err(CastError::NonScalar), + }; } - (FnPtr, t_cast) - } else { - return Err(CastError::NonScalar); + _ => return Err(CastError::NonScalar), } } _ => return Err(CastError::NonScalar), @@ -492,7 +518,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { match (t_from, t_cast) { // These types have invariants! can't cast into them. - (_, RPtr(_)) | (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar), + (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar), // * -> Bool (_, Int(Bool)) => Err(CastError::CastToBool), @@ -517,28 +543,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), - (RPtr(p), Int(_)) | - (RPtr(p), Float) => { - match p.ty.kind { - ty::Int(_) | - ty::Uint(_) | - ty::Float(_) => { - Err(CastError::NeedDeref) - } - ty::Infer(t) => { - match t { - ty::InferTy::IntVar(_) | - ty::InferTy::FloatVar(_) => Err(CastError::NeedDeref), - _ => Err(CastError::NeedViaPtr), - } - } - _ => Err(CastError::NeedViaPtr), - } - } + // * -> ptr (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), - (RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast // prim -> prim (Int(CEnum), Int(_)) => Ok(CastKind::EnumCast), From 35919ace7084e10fce15cb9bb42a9404b63b849d Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 20 Apr 2019 18:06:03 +0100 Subject: [PATCH 32/38] Start generating AddressOf rvalues in MIR `hir::BorrowKind::Raw` borrows and casting a reference to a raw pointer no longer do a reborrow followed by a cast. Instead we dereference and take the address. --- src/librustc_mir/build/expr/as_place.rs | 1 + src/librustc_mir/build/expr/as_rvalue.rs | 1 + src/librustc_mir/build/expr/category.rs | 1 + src/librustc_mir/build/expr/into.rs | 18 ++++ src/librustc_mir/hair/cx/expr.rs | 84 +++---------------- src/librustc_mir/hair/mod.rs | 5 ++ src/test/mir-opt/array-index-is-temporary.rs | 19 ++--- .../const_prop/const_prop_fails_gracefully.rs | 18 ++-- src/test/mir-opt/retag.rs | 10 +-- src/test/ui/cast/cast-as-bool.rs | 2 +- src/test/ui/cast/cast-as-bool.stderr | 7 +- 11 files changed, 61 insertions(+), 105 deletions(-) diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index ddacda72e1e65..15c7c92d7db51 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Pointer { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Match { .. } | ExprKind::Loop { .. } | ExprKind::Block { .. } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 37eb0cc9d961e..24282a6617acf 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::NeverToAny { .. } | ExprKind::Use { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Adt { .. } | ExprKind::Loop { .. } | ExprKind::LogicalOp { .. } diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index 270a1a6447435..4d0039b2e8cec 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -49,6 +49,7 @@ impl Category { | ExprKind::Use { .. } | ExprKind::Adt { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)), ExprKind::Array { .. } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 07a44b190b20a..6b33e8433f673 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -3,6 +3,7 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; +use rustc::hir; use rustc::mir::*; use rustc::ty::{self, CanonicalUserTypeAnnotation}; use rustc_data_structures::fx::FxHashMap; @@ -295,6 +296,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.push_assign(block, source_info, destination, borrow); block.unit() } + ExprKind::AddressOf { + mutability, + arg, + } => { + let address_of = match mutability { + hir::Mutability::Immutable => Rvalue::AddressOf( + Mutability::Not, + unpack!(block = this.as_read_only_place(block, arg)), + ), + hir::Mutability::Mutable => Rvalue::AddressOf( + Mutability::Mut, + unpack!(block = this.as_place(block, arg)), + ), + }; + this.cfg.push_assign(block, source_info, destination, address_of); + block.unit() + } ExprKind::Adt { adt_def, variant_index, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8c852854be1f9..6cbc25aa7356e 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -137,8 +137,11 @@ fn apply_adjustment<'a, 'tcx>( arg: expr.to_ref(), } } - Adjust::Borrow(AutoBorrow::RawPtr(mutbl)) => { - raw_ref_shim(cx, expr.to_ref(), adjustment.target, mutbl, span, temp_lifetime) + Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { + ExprKind::AddressOf { + mutability, + arg: expr.to_ref(), + } } }; @@ -262,17 +265,11 @@ fn make_mirror_unadjusted<'a, 'tcx>( } } - hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutbl, ref arg) => { - cx.tcx.sess - .struct_span_err( - expr.span, - "raw borrows are not yet implemented" - ) - .note("for more information, see https://github.com/rust-lang/rust/issues/64490") - .emit(); - - // Lower to an approximation to avoid further errors. - raw_ref_shim(cx, arg.to_ref(), expr_ty, mutbl, expr.span, temp_lifetime) + hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => { + ExprKind::AddressOf { + mutability, + arg: arg.to_ref(), + } } hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk }, @@ -1082,67 +1079,6 @@ fn convert_var( } -/// Fake `&raw [mut|const] expr` using a borrow and a cast until `AddressOf` -/// exists in MIR. -fn raw_ref_shim<'tcx>( - cx: &mut Cx<'_, 'tcx>, - arg: ExprRef<'tcx>, - ty: Ty<'tcx>, - mutbl: hir::Mutability, - span: Span, - temp_lifetime: Option, -) -> ExprKind<'tcx> { - let arg_tm = if let ty::RawPtr(type_mutbl) = ty.kind { - type_mutbl - } else { - bug!("raw_ref_shim called with non-raw pointer type"); - }; - // Convert this to a suitable `&foo` and - // then an unsafe coercion. - let borrow_expr = Expr { - temp_lifetime, - ty: cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, arg_tm), - span, - kind: ExprKind::Borrow { - borrow_kind: mutbl.to_borrow_kind(), - arg, - }, - }; - let cast_expr = Expr { - temp_lifetime, - ty, - span, - kind: ExprKind::Cast { source: borrow_expr.to_ref() } - }; - - // To ensure that both implicit and explicit coercions are - // handled the same way, we insert an extra layer of indirection here. - // For explicit casts (e.g., 'foo as *const T'), the source of the 'Use' - // will be an ExprKind::Hair with the appropriate cast expression. Here, - // we make our Use source the generated Cast from the original coercion. - // - // In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by - // as_operand, not by as_rvalue - causing the cast result to be stored in a temporary. - // Ordinary, this is identical to using the cast directly as an rvalue. However, if the - // source of the cast was previously borrowed as mutable, storing the cast in a - // temporary gives the source a chance to expire before the cast is used. For - // structs with a self-referential *mut ptr, this allows assignment to work as - // expected. - // - // For example, consider the type 'struct Foo { field: *mut Foo }', - // The method 'fn bar(&mut self) { self.field = self }' - // triggers a coercion from '&mut self' to '*mut self'. In order - // for the assignment to be valid, the implicit borrow - // of 'self' involved in the coercion needs to end before the local - // containing the '*mut T' is assigned to 'self.field' - otherwise, - // we end up trying to assign to 'self.field' while we have another mutable borrow - // active. - // - // We only need to worry about this kind of thing for coercions from refs to ptrs, - // since they get rid of a borrow implicitly. - ExprKind::Use { source: cast_expr.to_ref() } -} - fn bin_op(op: hir::BinOpKind) -> BinOp { match op { hir::BinOpKind::Add => BinOp::Add, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 47644d9ba8372..46e0d2a17b32d 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -212,6 +212,11 @@ pub enum ExprKind<'tcx> { borrow_kind: BorrowKind, arg: ExprRef<'tcx>, }, + /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`. + AddressOf { + mutability: hir::Mutability, + arg: ExprRef<'tcx>, + }, Break { label: region::Scope, value: Option>, diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array-index-is-temporary.rs index 00a6b26d0cf22..096f98bade25a 100644 --- a/src/test/mir-opt/array-index-is-temporary.rs +++ b/src/test/mir-opt/array-index-is-temporary.rs @@ -18,24 +18,23 @@ fn main() { // START rustc.main.EraseRegions.after.mir // bb0: { // ... -// _5 = &mut _2; -// _4 = &mut (*_5); -// _3 = move _4 as *mut usize (Misc); +// _4 = &mut _2; +// _3 = &raw mut (*_4); // ... -// _7 = _3; -// _6 = const foo(move _7) -> bb1; +// _6 = _3; +// _5 = const foo(move _6) -> bb1; // } // // bb1: { // ... -// _8 = _2; -// _9 = Len(_1); -// _10 = Lt(_8, _9); -// assert(move _10, "index out of bounds: the len is move _9 but the index is _8") -> bb2; +// _7 = _2; +// _8 = Len(_1); +// _9 = Lt(_7, _8); +// assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2; // } // // bb2: { -// _1[_8] = move _6; +// _1[_7] = move _5; // ... // return; // } diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs index 3f82b81a47de5..3c8c0ff449345 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs @@ -11,25 +11,21 @@ fn main() { // START rustc.main.ConstProp.before.mir // bb0: { // ... -// _3 = _4; -// _2 = move _3 as *const i32 (Misc); -// ... +// _2 = &raw const (*_3); // _1 = move _2 as usize (Misc); // ... -// _6 = _1; -// _5 = const read(move _6) -> bb1; +// _5 = _1; +// _4 = const read(move _5) -> bb1; // } // END rustc.main.ConstProp.before.mir // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _4 = const main::FOO; -// _3 = _4; -// _2 = move _3 as *const i32 (Misc); -// ... +// _3 = const main::FOO; +// _2 = &raw const (*_3); // _1 = move _2 as usize (Misc); // ... -// _6 = _1; -// _5 = const read(move _6) -> bb1; +// _5 = _1; +// _4 = const read(move _5) -> bb1; // } // END rustc.main.ConstProp.after.mir diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 32995448a21e9..ccecaeac96b83 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -82,18 +82,16 @@ fn main() { // _10 = move _8; // Retag(_10); // ... -// _13 = &mut (*_10); -// Retag(_13); -// _12 = move _13 as *mut i32 (Misc); +// _12 = &raw mut (*_10); // Retag([raw] _12); // ... -// _16 = move _17(move _18) -> bb5; +// _15 = move _16(move _17) -> bb5; // } // // bb5: { -// Retag(_16); +// Retag(_15); // ... -// _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7]; +// _19 = const Test::foo_shr(move _20, move _22) -> [return: bb6, unwind: bb7]; // } // // ... diff --git a/src/test/ui/cast/cast-as-bool.rs b/src/test/ui/cast/cast-as-bool.rs index 8130f4dedc9aa..1aed218aeb473 100644 --- a/src/test/ui/cast/cast-as-bool.rs +++ b/src/test/ui/cast/cast-as-bool.rs @@ -5,5 +5,5 @@ fn main() { let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool` //~| HELP compare with zero instead //~| SUGGESTION (1 + 2) != 0 - let v = "hello" as bool; //~ ERROR cannot cast as `bool` + let v = "hello" as bool; //~ ERROR casting `&'static str` as `bool` is invalid } diff --git a/src/test/ui/cast/cast-as-bool.stderr b/src/test/ui/cast/cast-as-bool.stderr index 30f8459c2e1e1..15d94ab69d88c 100644 --- a/src/test/ui/cast/cast-as-bool.stderr +++ b/src/test/ui/cast/cast-as-bool.stderr @@ -10,12 +10,13 @@ error[E0054]: cannot cast as `bool` LL | let t = (1 + 2) as bool; | ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0` -error[E0054]: cannot cast as `bool` +error[E0606]: casting `&'static str` as `bool` is invalid --> $DIR/cast-as-bool.rs:8:13 | LL | let v = "hello" as bool; - | ^^^^^^^^^^^^^^^ unsupported cast + | ^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0054`. +Some errors have detailed explanations: E0054, E0606. +For more information about an error, try `rustc --explain E0054`. From 5fb797ca753dfc5586ac277d5af4facab8c7c22f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 20 Apr 2019 18:06:10 +0100 Subject: [PATCH 33/38] Make slice drop shims use AddressOf --- src/librustc_mir/util/elaborate_drops.rs | 61 +++++++++--------------- src/test/mir-opt/slice-drop-shim.rs | 18 +++---- 2 files changed, 32 insertions(+), 47 deletions(-) diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 67e5bfafafd12..4f482431d3323 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -557,10 +557,10 @@ where /// if can_go then succ else drop-block /// drop-block: /// if ptr_based { - /// ptr = &mut *cur + /// ptr = cur /// cur = cur.offset(1) /// } else { - /// ptr = &mut P[cur] + /// ptr = &raw mut P[cur] /// cur = cur + 1 /// } /// drop(ptr) @@ -574,34 +574,28 @@ where unwind: Unwind, ptr_based: bool, ) -> BasicBlock { - let copy = |place: &Place<'tcx>| Operand::Copy(place.clone()); - let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); + let copy = |place: Place<'tcx>| Operand::Copy(place); + let move_ = |place: Place<'tcx>| Operand::Move(place); let tcx = self.tcx(); - let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { + let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { ty: ety, mutbl: hir::Mutability::Mutable }); - let ptr = &Place::from(self.new_temp(ref_ty)); - let can_go = &Place::from(self.new_temp(tcx.types.bool)); + let ptr = &Place::from(self.new_temp(ptr_ty)); + let can_go = Place::from(self.new_temp(tcx.types.bool)); let one = self.constant_usize(1); let (ptr_next, cur_next) = if ptr_based { - (Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - Place { - base: PlaceBase::Local(cur), - projection: tcx.intern_place_elems(&vec![ProjectionElem::Deref]), - } - ), - Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one)) + ( + Rvalue::Use(copy(cur.into())), + Rvalue::BinaryOp(BinOp::Offset, move_(cur.into()), one), + ) } else { - (Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - tcx.mk_place_index(self.place.clone(), cur)), - Rvalue::BinaryOp(BinOp::Add, move_(&Place::from(cur)), one)) + ( + Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place.clone(), cur)), + Rvalue::BinaryOp(BinOp::Add, move_(cur.into()), one), + ) }; let drop_block = BasicBlockData { @@ -620,9 +614,9 @@ where let loop_block = BasicBlockData { statements: vec![ - self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq, - copy(&Place::from(cur)), - copy(length_or_end))) + self.assign(&can_go, Rvalue::BinaryOp(BinOp::Eq, + copy(Place::from(cur)), + copy(length_or_end.clone()))) ], is_cleanup: unwind.is_cleanup(), terminator: Some(Terminator { @@ -725,8 +719,6 @@ where let cur = self.new_temp(iter_ty); let length_or_end = if ptr_based { - // FIXME check if we want to make it return a `Place` directly - // if all use sites want a `Place::Base` anyway. Place::from(self.new_temp(iter_ty)) } else { length.clone() @@ -753,23 +745,16 @@ where let drop_block_stmts = if ptr_based { let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); let tmp = Place::from(self.new_temp(tmp_ty)); - // tmp = &mut P; + // tmp = &raw mut P; // cur = tmp as *mut T; // end = Offset(cur, len); vec![ - self.assign(&tmp, Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - self.place.clone() - )), - self.assign( - &cur, - Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty), - ), + self.assign(&tmp, Rvalue::AddressOf(Mutability::Mut, self.place.clone())), + self.assign(&cur, Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty)), self.assign( &length_or_end, - Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length) - )), + Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length)), + ), ] } else { // cur = 0 (length already pushed) diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs index f270dec5fe232..5a37b67229c37 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -10,15 +10,15 @@ fn main() { // let mut _2: usize; // let mut _3: usize; // let mut _4: usize; -// let mut _5: &mut std::string::String; +// let mut _5: *mut std::string::String; // let mut _6: bool; -// let mut _7: &mut std::string::String; +// let mut _7: *mut std::string::String; // let mut _8: bool; // let mut _9: *mut std::string::String; // let mut _10: *mut std::string::String; -// let mut _11: &mut std::string::String; +// let mut _11: *mut std::string::String; // let mut _12: bool; -// let mut _13: &mut std::string::String; +// let mut _13: *mut std::string::String; // let mut _14: bool; // let mut _15: *mut [std::string::String]; // bb0: { @@ -31,7 +31,7 @@ fn main() { // resume; // } // bb3 (cleanup): { -// _5 = &mut (*_1)[_4]; +// _5 = &raw mut (*_1)[_4]; // _4 = Add(move _4, const 1usize); // drop((*_5)) -> bb4; // } @@ -40,7 +40,7 @@ fn main() { // switchInt(move _6) -> [false: bb3, otherwise: bb2]; // } // bb5: { -// _7 = &mut (*_1)[_4]; +// _7 = &raw mut (*_1)[_4]; // _4 = Add(move _4, const 1usize); // drop((*_7)) -> [return: bb6, unwind: bb4]; // } @@ -56,7 +56,7 @@ fn main() { // goto -> bb7; // } // bb9 (cleanup): { -// _11 = &mut (*_9); +// _11 = _9; // _9 = Offset(move _9, const 1usize); // drop((*_11)) -> bb10; // } @@ -65,7 +65,7 @@ fn main() { // switchInt(move _12) -> [false: bb9, otherwise: bb2]; // } // bb11: { -// _13 = &mut (*_9); +// _13 = _9; // _9 = Offset(move _9, const 1usize); // drop((*_13)) -> [return: bb12, unwind: bb10]; // } @@ -74,7 +74,7 @@ fn main() { // switchInt(move _14) -> [false: bb11, otherwise: bb1]; // } // bb13: { -// _15 = &mut (*_1); +// _15 = &raw mut (*_1); // _9 = move _15 as *mut std::string::String (Misc); // _10 = Offset(_9, move _3); // goto -> bb12; From 7081c79b7eed2c5b36674526d00c604b647027a3 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 20 Apr 2019 18:07:46 +0100 Subject: [PATCH 34/38] Add mir opt test for AddressOf --- src/test/mir-opt/address-of.rs | 112 +++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/test/mir-opt/address-of.rs diff --git a/src/test/mir-opt/address-of.rs b/src/test/mir-opt/address-of.rs new file mode 100644 index 0000000000000..bbd1ca68a8672 --- /dev/null +++ b/src/test/mir-opt/address-of.rs @@ -0,0 +1,112 @@ +fn address_of_reborrow() { + let y = &[0; 10]; + let mut z = &mut [0; 10]; + + y as *const _; + y as *const [i32; 10]; + y as *const dyn Send; + y as *const [i32]; + y as *const i32; // This is a cast, not a coercion + + let p: *const _ = y; + let p: *const [i32; 10] = y; + let p: *const dyn Send = y; + let p: *const [i32] = y; + + z as *const _; + z as *const [i32; 10]; + z as *const dyn Send; + z as *const [i32]; + + let p: *const _ = z; + let p: *const [i32; 10] = z; + let p: *const dyn Send = z; + let p: *const [i32] = z; + + z as *mut _; + z as *mut [i32; 10]; + z as *mut dyn Send; + z as *mut [i32]; + + let p: *mut _ = z; + let p: *mut [i32; 10] = z; + let p: *mut dyn Send = z; + let p: *mut [i32] = z; +} + +// The normal borrows here should be preserved +fn borrow_and_cast(mut x: i32) { + let p = &x as *const i32; + let q = &mut x as *const i32; + let r = &mut x as *mut i32; +} + +fn main() {} + +// START rustc.address_of_reborrow.SimplifyCfg-initial.after.mir +// bb0: { +// ... +// _5 = &raw const (*_1); // & to *const casts +// ... +// _7 = &raw const (*_1); +// ... +// _11 = &raw const (*_1); +// ... +// _14 = &raw const (*_1); +// ... +// _16 = &raw const (*_1); +// ... +// _17 = &raw const (*_1); // & to *const coercions +// ... +// _18 = &raw const (*_1); +// ... +// _20 = &raw const (*_1); +// ... +// _22 = &raw const (*_1); +// ... +// _24 = &raw const (*_2); // &mut to *const casts +// ... +// _26 = &raw const (*_2); +// ... +// _30 = &raw const (*_2); +// ... +// _33 = &raw const (*_2); +// ... +// _34 = &raw const (*_2); // &mut to *const coercions +// ... +// _35 = &raw const (*_2); +// ... +// _37 = &raw const (*_2); +// ... +// _39 = &raw const (*_2); +// ... +// _41 = &raw mut (*_2); // &mut to *mut casts +// ... +// _43 = &raw mut (*_2); +// ... +// _47 = &raw mut (*_2); +// ... +// _50 = &raw mut (*_2); +// ... +// _51 = &raw mut (*_2); // &mut to *mut coercions +// ... +// _52 = &raw mut (*_2); +// ... +// _54 = &raw mut (*_2); +// ... +// _56 = &raw mut (*_2); +// ... +// } +// END rustc.address_of_reborrow.SimplifyCfg-initial.after.mir + +// START rustc.borrow_and_cast.EraseRegions.after.mir +// bb0: { +// ... +// _4 = &_1; +// ... +// _7 = &mut _1; +// ... +// _10 = &mut _1; +// ... +// } +// END rustc.borrow_and_cast.EraseRegions.after.mir From 7b0cc6a439d2cf7a9d6dab5b1df2772488cc80a8 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 17 Sep 2019 19:32:40 +0100 Subject: [PATCH 35/38] Check const-propagation of borrows of unsized places --- src/test/ui/consts/const-prop-ice3.rs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/test/ui/consts/const-prop-ice3.rs diff --git a/src/test/ui/consts/const-prop-ice3.rs b/src/test/ui/consts/const-prop-ice3.rs new file mode 100644 index 0000000000000..8ab011661e3c5 --- /dev/null +++ b/src/test/ui/consts/const-prop-ice3.rs @@ -0,0 +1,7 @@ +// run-pass (ensure that const-prop is run) + +struct A(T); + +fn main() { + let _x = &(&A([2, 3]) as &A<[i32]>).0 as *const [i32] as *const i32; +} From 15931947f59e0010b73469711cb811f09aaf0cdd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 17 Sep 2019 21:18:15 +0100 Subject: [PATCH 36/38] Update test now that reference to pointer casts have more checks --- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 15 +++++- .../ui/consts/const-eval/ub-wide-ptr.stderr | 54 +++++++++++-------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 1f810c40572c0..a5c2a57c6c886 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -2,7 +2,6 @@ #![allow(unused)] #![allow(const_err)] // make sure we cannot allow away the errors tested here -// normalize-stderr-test "alignment \d+" -> "alignment N" // normalize-stderr-test "offset \d+" -> "offset N" // normalize-stderr-test "allocation \d+" -> "allocation N" // normalize-stderr-test "size \d+" -> "size N" @@ -149,11 +148,23 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 } //~^ ERROR it is undefined behavior to use this value // # raw trait object -const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; //~^ ERROR it is undefined behavior to use this value const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; //~^ ERROR it is undefined behavior to use this value const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw +// Const eval fails for these, so they need to be statics to error. +static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { + DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust + //~^ ERROR could not evaluate static initializer +}; +static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { + DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust + //~^ ERROR could not evaluate static initializer +}; + fn main() { + let _ = RAW_TRAIT_OBJ_VTABLE_NULL; + let _ = RAW_TRAIT_OBJ_VTABLE_INVALID; } diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 85fb8ac2a4a36..ce57d680dc95d 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:87:1 + --> $DIR/ub-wide-ptr.rs:86:1 | LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) @@ -7,7 +7,7 @@ LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:90:1 + --> $DIR/ub-wide-ptr.rs:89:1 | LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -15,7 +15,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:93:1 + --> $DIR/ub-wide-ptr.rs:92:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -23,7 +23,7 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRe = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:97:1 + --> $DIR/ub-wide-ptr.rs:96:1 | LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . @@ -31,7 +31,7 @@ LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:100:1 + --> $DIR/ub-wide-ptr.rs:99:1 | LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 @@ -39,7 +39,7 @@ LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:107:1 + --> $DIR/ub-wide-ptr.rs:106:1 | LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer @@ -47,7 +47,7 @@ LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.sli = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:110:1 + --> $DIR/ub-wide-ptr.rs:109:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) @@ -55,7 +55,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { p = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:113:1 + --> $DIR/ub-wide-ptr.rs:112:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -63,7 +63,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:117:1 + --> $DIR/ub-wide-ptr.rs:116:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 @@ -71,7 +71,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }. = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:123:1 + --> $DIR/ub-wide-ptr.rs:122:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 @@ -79,7 +79,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:126:1 + --> $DIR/ub-wide-ptr.rs:125:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 @@ -87,7 +87,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTrans = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:133:1 + --> $DIR/ub-wide-ptr.rs:132:1 | LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer @@ -95,7 +95,7 @@ LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:138:1 + --> $DIR/ub-wide-ptr.rs:137:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -103,7 +103,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:141:1 + --> $DIR/ub-wide-ptr.rs:140:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -111,7 +111,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:144:1 + --> $DIR/ub-wide-ptr.rs:143:1 | LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -119,7 +119,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDy = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:148:1 + --> $DIR/ub-wide-ptr.rs:147:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 @@ -127,21 +127,33 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:152:1 + --> $DIR/ub-wide-ptr.rs:151:1 | -LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:154:1 + --> $DIR/ub-wide-ptr.rs:153:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to 18 previous errors +error[E0080]: could not evaluate static initializer + --> $DIR/ub-wide-ptr.rs:159:5 + | +LL | DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer + +error[E0080]: could not evaluate static initializer + --> $DIR/ub-wide-ptr.rs:163:5 + | +LL | DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N + +error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0080`. From 6dcc78997f19822373ed17549004282da82851dc Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 18 Sep 2019 21:31:25 +0100 Subject: [PATCH 37/38] Add more tests for raw_ref_op --- src/librustc_error_codes/error_codes/E0745.md | 2 +- src/test/pretty/raw-address-of.rs | 12 +++ .../borrow-raw-address-of-borrowed.rs | 22 ++++++ .../borrow-raw-address-of-borrowed.stderr | 40 ++++++++++ ...rrow-raw-address-of-deref-mutability-ok.rs | 23 ++++++ .../borrow-raw-address-of-deref-mutability.rs | 17 +++++ ...row-raw-address-of-deref-mutability.stderr | 21 ++++++ .../borrow-raw-address-of-mutability-ok.rs | 44 +++++++++++ .../borrow-raw-address-of-mutability.rs | 42 +++++++++++ .../borrow-raw-address-of-mutability.stderr | 59 +++++++++++++++ .../consts/const-address-of-interior-mut.rs | 16 ++++ .../const-address-of-interior-mut.stderr | 27 +++++++ src/test/ui/consts/const-address-of-mut.rs | 14 ++++ .../ui/consts/const-address-of-mut.stderr | 39 ++++++++++ src/test/ui/consts/const-address-of.rs | 19 +++++ .../const-mut-refs/const_mut_address_of.rs | 30 ++++++++ src/test/ui/consts/min_const_fn/address_of.rs | 17 +++++ .../ui/consts/min_const_fn/address_of.stderr | 21 ++++++ .../consts/min_const_fn/address_of_const.rs | 19 +++++ src/test/ui/lint/lint-unused-mut-variables.rs | 8 +- .../ui/lint/lint-unused-mut-variables.stderr | 14 +++- .../packed-struct-address-of-element.rs | 37 ++++++++++ .../ui/packed/packed-struct-borrow-element.rs | 2 +- src/test/ui/raw-ref-op/raw-ref-op.rs | 6 +- src/test/ui/raw-ref-op/raw-ref-op.stderr | 18 ----- src/test/ui/raw-ref-op/raw-ref-temp-deref.rs | 20 ++--- .../ui/raw-ref-op/raw-ref-temp-deref.stderr | 74 ------------------- src/test/ui/raw-ref-op/raw-ref-temp.rs | 6 +- src/test/ui/raw-ref-op/raw-ref-temp.stderr | 40 +++++----- src/test/ui/raw-ref-op/unusual_locations.rs | 31 ++++---- .../ui/raw-ref-op/unusual_locations.stderr | 18 ----- 31 files changed, 590 insertions(+), 168 deletions(-) create mode 100644 src/test/pretty/raw-address-of.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-mutability.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr create mode 100644 src/test/ui/consts/const-address-of-interior-mut.rs create mode 100644 src/test/ui/consts/const-address-of-interior-mut.stderr create mode 100644 src/test/ui/consts/const-address-of-mut.rs create mode 100644 src/test/ui/consts/const-address-of-mut.stderr create mode 100644 src/test/ui/consts/const-address-of.rs create mode 100644 src/test/ui/consts/const-mut-refs/const_mut_address_of.rs create mode 100644 src/test/ui/consts/min_const_fn/address_of.rs create mode 100644 src/test/ui/consts/min_const_fn/address_of.stderr create mode 100644 src/test/ui/consts/min_const_fn/address_of_const.rs create mode 100644 src/test/ui/packed/packed-struct-address-of-element.rs delete mode 100644 src/test/ui/raw-ref-op/raw-ref-op.stderr delete mode 100644 src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr delete mode 100644 src/test/ui/raw-ref-op/unusual_locations.stderr diff --git a/src/librustc_error_codes/error_codes/E0745.md b/src/librustc_error_codes/error_codes/E0745.md index 39bebdcd3750e..6595691ce786c 100644 --- a/src/librustc_error_codes/error_codes/E0745.md +++ b/src/librustc_error_codes/error_codes/E0745.md @@ -11,7 +11,7 @@ fn temp_address() { To avoid the error, first bind the temporary to a named local variable. -```ignore (not yet implemented) +``` # #![feature(raw_ref_op)] fn temp_address() { let val = 2; diff --git a/src/test/pretty/raw-address-of.rs b/src/test/pretty/raw-address-of.rs new file mode 100644 index 0000000000000..6ccc434a1e79c --- /dev/null +++ b/src/test/pretty/raw-address-of.rs @@ -0,0 +1,12 @@ +// pp-exact +#![feature(raw_ref_op)] + +const C_PTR: () = { let a = 1; &raw const a; }; +static S_PTR: () = { let b = false; &raw const b; }; + +fn main() { + let x = 123; + let mut y = 345; + let c_p = &raw const x; + let parens = unsafe { *(&raw mut (y)) }; +} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs new file mode 100644 index 0000000000000..f25fd7f66b3cc --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs @@ -0,0 +1,22 @@ +#![feature(raw_ref_op)] + +fn address_of_shared() { + let mut x = 0; + let y = &x; + + let q = &raw mut x; //~ ERROR cannot borrow + + drop(y); +} + +fn address_of_mutably_borrowed() { + let mut x = 0; + let y = &mut x; + + let p = &raw const x; //~ ERROR cannot borrow + let q = &raw mut x; //~ ERROR cannot borrow + + drop(y); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr new file mode 100644 index 0000000000000..ff461b748be88 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr @@ -0,0 +1,40 @@ +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/borrow-raw-address-of-borrowed.rs:7:13 + | +LL | let y = &x; + | -- immutable borrow occurs here +LL | +LL | let q = &raw mut x; + | ^^^^^^^^^^ mutable borrow occurs here +LL | +LL | drop(y); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrow-raw-address-of-borrowed.rs:16:13 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | +LL | let p = &raw const x; + | ^^^^^^^^^^^^ immutable borrow occurs here +... +LL | drop(y); + | - mutable borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrow-raw-address-of-borrowed.rs:17:13 + | +LL | let y = &mut x; + | ------ first mutable borrow occurs here +... +LL | let q = &raw mut x; + | ^^^^^^^^^^ second mutable borrow occurs here +LL | +LL | drop(y); + | - first borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs new file mode 100644 index 0000000000000..e381384fe65ec --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(raw_ref_op)] + +fn raw_reborrow() { + let x = &0; + let y = &mut 0; + + let p = &raw const *x; + let r = &raw const *y; + let s = &raw mut *y; +} + +unsafe fn raw_reborrow_of_raw() { + let x = &0 as *const i32; + let y = &mut 0 as *mut i32; + + let p = &raw const *x; + let r = &raw const *y; + let s = &raw mut *y; +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs new file mode 100644 index 0000000000000..712873528b5f1 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs @@ -0,0 +1,17 @@ +// Check that `&raw mut` cannot be used to turn a `&T` into a `*mut T`. + +#![feature(raw_ref_op)] + +fn raw_reborrow() { + let x = &0; + + let q = &raw mut *x; //~ ERROR cannot borrow +} + +unsafe fn raw_reborrow_of_raw() { + let x = &0 as *const i32; + + let q = &raw mut *x; //~ ERROR cannot borrow +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr new file mode 100644 index 0000000000000..31af38507c7d7 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr @@ -0,0 +1,21 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrow-raw-address-of-deref-mutability.rs:8:13 + | +LL | let x = &0; + | -- help: consider changing this to be a mutable reference: `&mut 0` +LL | +LL | let q = &raw mut *x; + | ^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer + --> $DIR/borrow-raw-address-of-deref-mutability.rs:14:13 + | +LL | let x = &0 as *const i32; + | -- help: consider changing this to be a mutable pointer: `&mut 0` +LL | +LL | let q = &raw mut *x; + | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs new file mode 100644 index 0000000000000..e1cf2dc53869b --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs @@ -0,0 +1,44 @@ +// check-pass + +#![feature(raw_ref_op)] + +fn mutable_address_of() { + let mut x = 0; + let y = &raw mut x; +} + +fn mutable_address_of_closure() { + let mut x = 0; + let mut f = || { + let y = &raw mut x; + }; + f(); +} + +fn const_address_of_closure() { + let x = 0; + let f = || { + let y = &raw const x; + }; + f(); +} + +fn make_fn(f: F) -> F { f } + +fn const_address_of_fn_closure() { + let x = 0; + let f = make_fn(|| { + let y = &raw const x; + }); + f(); +} + +fn const_address_of_fn_closure_move() { + let x = 0; + let f = make_fn(move || { + let y = &raw const x; + }); + f(); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs new file mode 100644 index 0000000000000..320c54b806a72 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs @@ -0,0 +1,42 @@ +#![feature(raw_ref_op)] + +fn mutable_address_of() { + let x = 0; + let y = &raw mut x; //~ ERROR cannot borrow +} + +fn mutable_address_of_closure() { + let x = 0; + let mut f = || { + let y = &raw mut x; //~ ERROR cannot borrow + }; + f(); +} + +fn mutable_address_of_imm_closure() { + let mut x = 0; + let f = || { + let y = &raw mut x; + }; + f(); //~ ERROR cannot borrow +} + +fn make_fn(f: F) -> F { f } + +fn mutable_address_of_fn_closure() { + let mut x = 0; + let f = make_fn(|| { + let y = &raw mut x; //~ ERROR cannot borrow + }); + f(); +} + +fn mutable_address_of_fn_closure_move() { + let mut x = 0; + let f = make_fn(move || { + let y = &raw mut x; //~ ERROR cannot borrow + }); + f(); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr new file mode 100644 index 0000000000000..cf01c362d50bc --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -0,0 +1,59 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:5:13 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:11:17 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | let mut f = || { +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:21:5 + | +LL | let f = || { + | - help: consider changing this to be mutable: `mut f` +... +LL | f(); + | ^ cannot borrow as mutable + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-raw-address-of-mutability.rs:29:17 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to accept closures that implement `FnMut` + --> $DIR/borrow-raw-address-of-mutability.rs:28:21 + | +LL | let f = make_fn(|| { + | _____________________^ +LL | | let y = &raw mut x; +LL | | }); + | |_____^ + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-raw-address-of-mutability.rs:37:17 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to accept closures that implement `FnMut` + --> $DIR/borrow-raw-address-of-mutability.rs:36:21 + | +LL | let f = make_fn(move || { + | _____________________^ +LL | | let y = &raw mut x; +LL | | }); + | |_____^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/consts/const-address-of-interior-mut.rs b/src/test/ui/consts/const-address-of-interior-mut.rs new file mode 100644 index 0000000000000..60c7c31daca78 --- /dev/null +++ b/src/test/ui/consts/const-address-of-interior-mut.rs @@ -0,0 +1,16 @@ +#![feature(raw_ref_op)] + +use std::cell::Cell; + +const A: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +static B: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +static mut C: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +const fn foo() { + let x = Cell::new(0); + let y = &raw const x; //~ ERROR interior mutability +} + +fn main() {} diff --git a/src/test/ui/consts/const-address-of-interior-mut.stderr b/src/test/ui/consts/const-address-of-interior-mut.stderr new file mode 100644 index 0000000000000..f15174c33b3a0 --- /dev/null +++ b/src/test/ui/consts/const-address-of-interior-mut.stderr @@ -0,0 +1,27 @@ +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:5:39 + | +LL | const A: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:7:40 + | +LL | static B: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:9:44 + | +LL | static mut C: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:13:13 + | +LL | let y = &raw const x; + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0492`. diff --git a/src/test/ui/consts/const-address-of-mut.rs b/src/test/ui/consts/const-address-of-mut.rs new file mode 100644 index 0000000000000..fe9188cb4904c --- /dev/null +++ b/src/test/ui/consts/const-address-of-mut.rs @@ -0,0 +1,14 @@ +#![feature(raw_ref_op)] + +const A: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed + +static B: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed + +static mut C: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed + +const fn foo() { + let mut x = 0; + let y = &raw mut x; //~ ERROR `&raw mut` is not allowed +} + +fn main() {} diff --git a/src/test/ui/consts/const-address-of-mut.stderr b/src/test/ui/consts/const-address-of-mut.stderr new file mode 100644 index 0000000000000..15f2296c42c25 --- /dev/null +++ b/src/test/ui/consts/const-address-of-mut.stderr @@ -0,0 +1,39 @@ +error[E0658]: `&raw mut` is not allowed in constants + --> $DIR/const-address-of-mut.rs:3:32 + | +LL | const A: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in statics + --> $DIR/const-address-of-mut.rs:5:33 + | +LL | static B: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in statics + --> $DIR/const-address-of-mut.rs:7:37 + | +LL | static mut C: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in constant functions + --> $DIR/const-address-of-mut.rs:11:13 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-address-of.rs b/src/test/ui/consts/const-address-of.rs new file mode 100644 index 0000000000000..ba162f2a2badf --- /dev/null +++ b/src/test/ui/consts/const-address-of.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(raw_ref_op)] + +const A: *const i32 = &raw const *&2; +static B: () = { &raw const *&2; }; +static mut C: *const i32 = &raw const *&2; +const D: () = { let x = 2; &raw const x; }; +static E: () = { let x = 2; &raw const x; }; +static mut F: () = { let x = 2; &raw const x; }; + +const fn const_ptr() { + let x = 0; + let ptr = &raw const x; + let r = &x; + let ptr2 = &raw const *r; +} + +fn main() {} diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs new file mode 100644 index 0000000000000..130ba9283b1d9 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -0,0 +1,30 @@ +// check-pass + +#![feature(const_mut_refs)] +#![feature(const_fn)] +#![feature(raw_ref_op)] + +struct Foo { + x: usize +} + +const fn foo() -> Foo { + Foo { x: 0 } +} + +impl Foo { + const fn bar(&mut self) -> *mut usize { + &raw mut self.x + } +} + +const fn baz(foo: &mut Foo)-> *mut usize { + &raw mut foo.x +} + +const _: () = { + foo().bar(); + baz(&mut foo()); +}; + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/address_of.rs b/src/test/ui/consts/min_const_fn/address_of.rs new file mode 100644 index 0000000000000..f8506d70b2498 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of.rs @@ -0,0 +1,17 @@ +#![feature(raw_ref_op)] + +const fn mutable_address_of_in_const() { + let mut a = 0; + let b = &raw mut a; //~ ERROR `&raw mut` is not allowed +} + +struct X; + +impl X { + const fn inherent_mutable_address_of_in_const() { + let mut a = 0; + let b = &raw mut a; //~ ERROR `&raw mut` is not allowed + } +} + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/address_of.stderr b/src/test/ui/consts/min_const_fn/address_of.stderr new file mode 100644 index 0000000000000..3554b8112b168 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of.stderr @@ -0,0 +1,21 @@ +error[E0658]: `&raw mut` is not allowed in constant functions + --> $DIR/address_of.rs:5:13 + | +LL | let b = &raw mut a; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in constant functions + --> $DIR/address_of.rs:13:17 + | +LL | let b = &raw mut a; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/address_of_const.rs b/src/test/ui/consts/min_const_fn/address_of_const.rs new file mode 100644 index 0000000000000..3db19e9cde8f0 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of_const.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(raw_ref_op)] + +const fn const_address_of_in_const() { + let mut a = 0; + let b = &raw const a; +} + +struct X; + +impl X { + const fn inherent_const_address_of_in_const() { + let mut a = 0; + let b = &raw const a; + } +} + +fn main() {} diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index 1af44ecf362bf..dd8dbda6d4303 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -3,7 +3,7 @@ // Exercise the unused_mut attribute in some positive and negative cases #![deny(unused_mut)] -#![feature(async_closure)] +#![feature(async_closure, raw_ref_op)] async fn baz_async( mut a: i32, @@ -177,6 +177,12 @@ fn main() { // leading underscore should avoid the warning, just like the // unused variable lint. let mut _allowed = 1; + + let mut raw_address_of_mut = 1; // OK + let mut_ptr = &raw mut raw_address_of_mut; + + let mut raw_address_of_const = 1; //~ ERROR: variable does not need to be mutable + let const_ptr = &raw const raw_address_of_const; } fn callback(f: F) where F: FnOnce() {} diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr index 92c2b68652dc2..c1ab0ab33d4cc 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.stderr +++ b/src/test/ui/lint/lint-unused-mut-variables.stderr @@ -180,6 +180,14 @@ LL | let mut v : &mut Vec<()> = &mut vec![]; | | | help: remove this `mut` +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:184:9 + | +LL | let mut raw_address_of_const = 1; + | ----^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:106:13 | @@ -197,7 +205,7 @@ LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { | help: remove this `mut` error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:196:9 + --> $DIR/lint-unused-mut-variables.rs:202:9 | LL | let mut b = vec![2]; | ----^ @@ -205,10 +213,10 @@ LL | let mut b = vec![2]; | help: remove this `mut` | note: lint level defined here - --> $DIR/lint-unused-mut-variables.rs:192:8 + --> $DIR/lint-unused-mut-variables.rs:198:8 | LL | #[deny(unused_mut)] | ^^^^^^^^^^ -error: aborting due to 25 previous errors +error: aborting due to 26 previous errors diff --git a/src/test/ui/packed/packed-struct-address-of-element.rs b/src/test/ui/packed/packed-struct-address-of-element.rs new file mode 100644 index 0000000000000..812d23fb58023 --- /dev/null +++ b/src/test/ui/packed/packed-struct-address-of-element.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(dead_code)] +#![deny(safe_packed_borrows)] +#![feature(raw_ref_op)] +// ignore-emscripten weird assertion? + +#[repr(packed)] +struct Foo1 { + bar: u8, + baz: usize +} + +#[repr(packed(2))] +struct Foo2 { + bar: u8, + baz: usize +} + +#[repr(C, packed(4))] +struct Foo4C { + bar: u8, + baz: usize +} + +pub fn main() { + let foo = Foo1 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let foo = Foo2 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let mut foo = Foo4C { bar: 1, baz: 2 }; + let brw = &raw mut foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } +} diff --git a/src/test/ui/packed/packed-struct-borrow-element.rs b/src/test/ui/packed/packed-struct-borrow-element.rs index 6ac42ed0d471b..0072b6191ebb0 100644 --- a/src/test/ui/packed/packed-struct-borrow-element.rs +++ b/src/test/ui/packed/packed-struct-borrow-element.rs @@ -1,4 +1,4 @@ -// run-pass +// run-pass (note: this is spec-UB, but it works for now) #![allow(dead_code)] // ignore-emscripten weird assertion? diff --git a/src/test/ui/raw-ref-op/raw-ref-op.rs b/src/test/ui/raw-ref-op/raw-ref-op.rs index de847909eb371..0c6e23a00d525 100644 --- a/src/test/ui/raw-ref-op/raw-ref-op.rs +++ b/src/test/ui/raw-ref-op/raw-ref-op.rs @@ -1,11 +1,11 @@ -// FIXME(#64490): make this run-pass +// run-pass #![feature(raw_ref_op)] fn main() { let mut x = 123; - let c_p = &raw const x; //~ ERROR not yet implemented - let m_p = &raw mut x; //~ ERROR not yet implemented + let c_p = &raw const x; + let m_p = &raw mut x; let i_r = &x; assert!(c_p == i_r); assert!(c_p == m_p); diff --git a/src/test/ui/raw-ref-op/raw-ref-op.stderr b/src/test/ui/raw-ref-op/raw-ref-op.stderr deleted file mode 100644 index 04c59c95fca1e..0000000000000 --- a/src/test/ui/raw-ref-op/raw-ref-op.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/raw-ref-op.rs:7:15 - | -LL | let c_p = &raw const x; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-op.rs:8:15 - | -LL | let m_p = &raw mut x; - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs index d251586de5595..a814003aebf20 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs @@ -1,4 +1,4 @@ -// FIXME(#64490) This should be check-pass +// check-pass // Check that taking the address of a place that contains a dereference is // allowed. #![feature(raw_ref_op, type_ascription)] @@ -10,15 +10,15 @@ const SLICE_REF: &[i32] = &[5, 6]; fn main() { // These are all OK, we're not taking the address of the temporary - let deref_ref = &raw const *PAIR_REF; //~ ERROR not yet implemented - let field_deref_ref = &raw const PAIR_REF.0; //~ ERROR not yet implemented - let deref_ref = &raw const *ARRAY_REF; //~ ERROR not yet implemented - let index_deref_ref = &raw const ARRAY_REF[0]; //~ ERROR not yet implemented - let deref_ref = &raw const *SLICE_REF; //~ ERROR not yet implemented - let index_deref_ref = &raw const SLICE_REF[1]; //~ ERROR not yet implemented + let deref_ref = &raw const *PAIR_REF; + let field_deref_ref = &raw const PAIR_REF.0; + let deref_ref = &raw const *ARRAY_REF; + let index_deref_ref = &raw const ARRAY_REF[0]; + let deref_ref = &raw const *SLICE_REF; + let index_deref_ref = &raw const SLICE_REF[1]; let x = 0; - let ascribe_ref = &raw const (x: i32); //~ ERROR not yet implemented - let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); //~ ERROR not yet implemented - let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); //~ ERROR not yet implemented + let ascribe_ref = &raw const (x: i32); + let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); + let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); } diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr b/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr deleted file mode 100644 index b0bfc74903b0c..0000000000000 --- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr +++ /dev/null @@ -1,74 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:13:21 - | -LL | let deref_ref = &raw const *PAIR_REF; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:14:27 - | -LL | let field_deref_ref = &raw const PAIR_REF.0; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:15:21 - | -LL | let deref_ref = &raw const *ARRAY_REF; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:16:27 - | -LL | let index_deref_ref = &raw const ARRAY_REF[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:17:21 - | -LL | let deref_ref = &raw const *SLICE_REF; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:18:27 - | -LL | let index_deref_ref = &raw const SLICE_REF[1]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:21:23 - | -LL | let ascribe_ref = &raw const (x: i32); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:22:25 - | -LL | let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:23:31 - | -LL | let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 9 previous errors - diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.rs b/src/test/ui/raw-ref-op/raw-ref-temp.rs index ac2445f049c66..32df56468da17 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp.rs @@ -1,6 +1,8 @@ // Ensure that we don't allow taking the address of temporary values #![feature(raw_ref_op, type_ascription)] +const FOUR: u64 = 4; + const PAIR: (i32, i64) = (1, 2); const ARRAY: [i32; 2] = [1, 2]; @@ -8,8 +10,8 @@ const ARRAY: [i32; 2] = [1, 2]; fn main() { let ref_expr = &raw const 2; //~ ERROR cannot take address let mut_ref_expr = &raw mut 3; //~ ERROR cannot take address - let ref_const = &raw const 4; //~ ERROR cannot take address - let mut_ref_const = &raw mut 5; //~ ERROR cannot take address + let ref_const = &raw const FOUR; //~ ERROR cannot take address + let mut_ref_const = &raw mut FOUR; //~ ERROR cannot take address let field_ref_expr = &raw const (1, 2).0; //~ ERROR cannot take address let mut_field_ref_expr = &raw mut (1, 2).0; //~ ERROR cannot take address diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.stderr b/src/test/ui/raw-ref-op/raw-ref-temp.stderr index de07073373506..80dea76d5953b 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.stderr +++ b/src/test/ui/raw-ref-op/raw-ref-temp.stderr @@ -1,95 +1,95 @@ error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:9:31 + --> $DIR/raw-ref-temp.rs:11:31 | LL | let ref_expr = &raw const 2; | ^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:10:33 + --> $DIR/raw-ref-temp.rs:12:33 | LL | let mut_ref_expr = &raw mut 3; | ^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:11:32 + --> $DIR/raw-ref-temp.rs:13:32 | -LL | let ref_const = &raw const 4; - | ^ temporary value +LL | let ref_const = &raw const FOUR; + | ^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:12:34 + --> $DIR/raw-ref-temp.rs:14:34 | -LL | let mut_ref_const = &raw mut 5; - | ^ temporary value +LL | let mut_ref_const = &raw mut FOUR; + | ^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:14:37 + --> $DIR/raw-ref-temp.rs:16:37 | LL | let field_ref_expr = &raw const (1, 2).0; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:15:39 + --> $DIR/raw-ref-temp.rs:17:39 | LL | let mut_field_ref_expr = &raw mut (1, 2).0; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:16:32 + --> $DIR/raw-ref-temp.rs:18:32 | LL | let field_ref = &raw const PAIR.0; | ^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:17:34 + --> $DIR/raw-ref-temp.rs:19:34 | LL | let mut_field_ref = &raw mut PAIR.0; | ^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:19:37 + --> $DIR/raw-ref-temp.rs:21:37 | LL | let index_ref_expr = &raw const [1, 2][0]; | ^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:20:39 + --> $DIR/raw-ref-temp.rs:22:39 | LL | let mut_index_ref_expr = &raw mut [1, 2][0]; | ^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:21:32 + --> $DIR/raw-ref-temp.rs:23:32 | LL | let index_ref = &raw const ARRAY[0]; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:22:34 + --> $DIR/raw-ref-temp.rs:24:34 | LL | let mut_index_ref = &raw mut ARRAY[1]; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:24:34 + --> $DIR/raw-ref-temp.rs:26:34 | LL | let ref_ascribe = &raw const (2: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:25:36 + --> $DIR/raw-ref-temp.rs:27:36 | LL | let mut_ref_ascribe = &raw mut (3: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:27:40 + --> $DIR/raw-ref-temp.rs:29:40 | LL | let ascribe_field_ref = &raw const (PAIR.0: i32); | ^^^^^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:28:38 + --> $DIR/raw-ref-temp.rs:30:38 | LL | let ascribe_index_ref = &raw mut (ARRAY[0]: i32); | ^^^^^^^^^^^^^^^ temporary value diff --git a/src/test/ui/raw-ref-op/unusual_locations.rs b/src/test/ui/raw-ref-op/unusual_locations.rs index f0a6bcce2ac8a..6bf37408a8bbd 100644 --- a/src/test/ui/raw-ref-op/unusual_locations.rs +++ b/src/test/ui/raw-ref-op/unusual_locations.rs @@ -1,25 +1,22 @@ -// FIXME(#64490): make this check-pass +// check-pass #![feature(raw_ref_op)] -const USES_PTR: () = { let u = (); &raw const u; }; //~ ERROR not yet implemented -static ALSO_USES_PTR: () = { let u = (); &raw const u; }; //~ ERROR not yet implemented +const USES_PTR: () = { let u = (); &raw const u; }; +static ALSO_USES_PTR: () = { let u = (); &raw const u; }; fn main() { - #[cfg(FALSE)] - { - let x: [i32; { let u = 2; let x = &raw const u; 4 }] - = [2; { let v = 3; let y = &raw const v; 4 }]; - let mut one = 1; - let two = 2; - if &raw const one == &raw mut one { - match &raw const two { - _ => {} - } + let x: [i32; { let u = 2; let x = &raw const u; 4 }] + = [2; { let v = 3; let y = &raw const v; 4 }]; + let mut one = 1; + let two = 2; + if &raw const one == &raw mut one { + match &raw const two { + _ => {} } - let three = 3; - let mut four = 4; - println!("{:p}", &raw const three); - unsafe { &raw mut four; } } + let three = 3; + let mut four = 4; + println!("{:p}", &raw const three); + unsafe { &raw mut four; } } diff --git a/src/test/ui/raw-ref-op/unusual_locations.stderr b/src/test/ui/raw-ref-op/unusual_locations.stderr deleted file mode 100644 index 3fae5db3d51a1..0000000000000 --- a/src/test/ui/raw-ref-op/unusual_locations.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/unusual_locations.rs:5:36 - | -LL | const USES_PTR: () = { let u = (); &raw const u; }; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/unusual_locations.rs:6:42 - | -LL | static ALSO_USES_PTR: () = { let u = (); &raw const u; }; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 2 previous errors - From a74911662e8de2c024ea188e4dcac6a494c74455 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 2 Dec 2019 22:20:35 +0000 Subject: [PATCH 38/38] Fix comment ordering --- src/libsyntax/ast.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 92ba071a03d68..274e19ec3e425 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -728,13 +728,13 @@ impl Mutability { #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(RustcEncodable, RustcDecodable, HashStable_Generic)] pub enum BorrowKind { - /// A raw borrow, `&raw const $expr` or `&raw mut $expr`. - /// The resulting type is either `*const T` or `*mut T` - /// where `T = typeof($expr)`. - Ref, /// A normal borrow, `&$expr` or `&mut $expr`. /// The resulting type is either `&'a T` or `&'a mut T` /// where `T = typeof($expr)` and `'a` is some lifetime. + Ref, + /// A raw borrow, `&raw const $expr` or `&raw mut $expr`. + /// The resulting type is either `*const T` or `*mut T` + /// where `T = typeof($expr)`. Raw, }