From d419a5fdaebb36dbf3c600f624c964d9ea651661 Mon Sep 17 00:00:00 2001 From: Janusz Marcinkiewicz Date: Sun, 1 Dec 2019 13:39:01 +0100 Subject: 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 (limited to 'src') diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c7a0190a1d1..5e644df99be 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 00000000000..a452e6384a3 --- /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 00000000000..a2eec7caee5 --- /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`. -- cgit 1.4.1-3-g733a5 From e305bf8bc8cecaf93080f07962a4f763cd66f5ce Mon Sep 17 00:00:00 2001 From: Janusz Marcinkiewicz Date: Tue, 3 Dec 2019 08:20:17 +0100 Subject: Rename tests and add short test description --- .../array-impls/core-traits-no-impls-length-33.rs | 1 + .../array-impls/core-traits-no-impls-length-33.stderr | 19 ++++++++++++++----- .../issues/issue-66923-show-error-for-correct-call.rs | 15 +++++++++++++++ .../issue-66923-show-error-for-correct-call.stderr | 19 +++++++++++++++++++ src/test/ui/issues/issue-66923.rs | 13 ------------- src/test/ui/issues/issue-66923.stderr | 19 ------------------- 6 files changed, 49 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/issues/issue-66923-show-error-for-correct-call.rs create mode 100644 src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr delete mode 100644 src/test/ui/issues/issue-66923.rs delete mode 100644 src/test/ui/issues/issue-66923.stderr (limited to 'src') 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 8397d204f35..7fa059583f5 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 594a0d4b5d8..d885c98dcb2 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-show-error-for-correct-call.rs b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs new file mode 100644 index 00000000000..83328073972 --- /dev/null +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs @@ -0,0 +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 value of type + fft.push(x2); + + let x3 = x1.into_iter().collect::>(); + //~^ 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 00000000000..8e7ee97e0b9 --- /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.rs b/src/test/ui/issues/issue-66923.rs deleted file mode 100644 index a452e6384a3..00000000000 --- a/src/test/ui/issues/issue-66923.rs +++ /dev/null @@ -1,13 +0,0 @@ -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 deleted file mode 100644 index a2eec7caee5..00000000000 --- 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`. -- cgit 1.4.1-3-g733a5 From c4bbe9cbbe9921646cdedb856e34dc951641ed96 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 30 Nov 2019 18:25:44 +0100 Subject: 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 +-- .../ui/parser/macro/trait-non-item-macros.stderr | 4 +-- .../missing-close-brace-in-trait.stderr | 4 +-- .../trait-item-with-defaultness-fail-semantic.rs | 10 ++++++ ...rait-item-with-defaultness-fail-semantic.stderr | 38 ++++++++++++++++++++++ .../ui/parser/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 (limited to 'src') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 34ef12e818c..c159fb66d50 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 202b6ae2f94..a078a36db7a 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 92ba071a03d..964acfa92b9 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 f8795d885d2..9d0a29f2951 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 f0c5fb32fb1..2e3ea5e2444 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 faea04e691b..6057be9826a 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 e0b15130c33..e8ef981f515 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 70256a59231..1a97f54160b 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 0a433ab278e..7647ba500e0 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 cbaf9315e85..7e8abf22d55 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 00000000000..b67e30637aa --- /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 00000000000..48b502a1506 --- /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 00000000000..a6318bd99e2 --- /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() {} +} -- cgit 1.4.1-3-g733a5 From 73557faed23678fc443f3fa52727b5f200f597d2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 04:12:28 +0100 Subject: 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 +++++++ .../ui/parser/impl-item-const-semantic-fail.rs | 7 ++++++ .../ui/parser/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 (limited to 'src') diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index ff9d8c85df8..32b36d2021b 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 c159fb66d50..68fdfd24d61 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 a078a36db7a..ba0e6b100ee 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 396d9484339..97cbcb6401c 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 964acfa92b9..17a57387da7 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 9d0a29f2951..14701455013 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 2e3ea5e2444..c1405e15819 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 4ee09b4b87a..0b7a7d993aa 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 00000000000..d1124561374 --- /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 00000000000..5d4692f9f14 --- /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 00000000000..31a15f8e80e --- /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 + -- cgit 1.4.1-3-g733a5 From f6403c6c766c704569564b9021071c4917d45a25 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 07:24:07 +0100 Subject: 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 +++++- .../ui/parser/impl-item-const-semantic-fail.stderr | 4 +- src/test/ui/parser/impl-item-fn-no-body-pass.rs | 8 +++ .../parser/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 (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e13f6cabb52..a82febba38a 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 32b36d2021b..7e231cd6b59 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 68fdfd24d61..053502c43dc 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 ba0e6b100ee..78866dc9cc9 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 dd6b1d2119e..76a52bb7f7f 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 97cbcb6401c..99f9c3b1f2e 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 17a57387da7..f6af5d8637e 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 14701455013..0fa4dcf3ad9 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 c1405e15819..34097841b4a 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 0b7a7d993aa..bdf70ec46f7 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 5bd84b43a78..e8c4f993d4f 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 db3984cd189..8b1a39a94e6 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 58ab0a142d6..0ea6b017548 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 31a15f8e80e..ec3bee0ce68 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 00000000000..16b09d64e8c --- /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 00000000000..cb183db5964 --- /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 00000000000..1acb727368b --- /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 + -- cgit 1.4.1-3-g733a5 From c02fd3130284921f7077f78271b5501b402ec469 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 08:41:35 +0100 Subject: `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(-) (limited to 'src') diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 7e231cd6b59..ec78bcf1403 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 053502c43dc..5bfecf78e71 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 e2578d67e73..d2d5a33ec7a 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 76a52bb7f7f..471e2634b8a 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 4f95d6fe70f..d32a6a4b3e6 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 99f9c3b1f2e..bd7851296dd 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 f6af5d8637e..4e2f78e8ab8 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 3d2c3b1d4f9..10f6bbb5949 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 0fa4dcf3ad9..66cac0f917d 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 34097841b4a..00dcd7e8d0b 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 bdf70ec46f7..f96290ec4f8 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); } -- cgit 1.4.1-3-g733a5 From 39073767a483d10f8b4b2ac2f32bc9573d9dabbf Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:25:45 +0100 Subject: 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 +- src/test/ui/parser/impl-item-type-no-body-pass.rs | 11 ++++ .../parser/impl-item-type-no-body-semantic-fail.rs | 22 +++++++ .../impl-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 (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a82febba38a..54ff1f56eec 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 ec78bcf1403..f77523e6382 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 5bfecf78e71..302fcba4cf8 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 78866dc9cc9..f4b28077e9f 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 81f06a14d95..f01867f32c6 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 d32a6a4b3e6..33e24c8cfd4 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 bd7851296dd..d63a9df8d9b 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 4e2f78e8ab8..89868a9cd29 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 10f6bbb5949..f786de6401a 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 66cac0f917d..bb0462c19cd 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 00dcd7e8d0b..03e394b8c7e 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 f96290ec4f8..7cc1a769e52 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 e8c4f993d4f..d51fcf315a6 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 00000000000..74a9c6ab7e8 --- /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 00000000000..71c7d4ba21d --- /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 00000000000..6f1439c8f0b --- /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`. -- cgit 1.4.1-3-g733a5 From 92a372b0204a5f18286ff94648b98e4c0d6d27d2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:46:06 +0100 Subject: Unify `{Impl,Trait}Item` as `AssocItem`. --- src/libsyntax/ast.rs | 41 ++++++++++++++++++++++++----------------- src/libsyntax/attr/mod.rs | 2 +- 2 files changed, 25 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 89868a9cd29..dd8a7fa8665 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 079a0f6fafa..13a9ed5f215 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 } -- cgit 1.4.1-3-g733a5 From 2d92aa5535e9b28f4c9244785baed719b72b9d59 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:53:20 +0100 Subject: Fuse associated constant parsing. --- src/librustc_parse/parser/item.rs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 302fcba4cf8..d07fe358272 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: -- cgit 1.4.1-3-g733a5 From 10270bcd30d1d85a003412e597e367f2e7c89942 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:55:41 +0100 Subject: Fuse associated type parsing. --- src/librustc_parse/parser/item.rs | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d07fe358272..3fc4cafc0da 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`. -- cgit 1.4.1-3-g733a5 From 7672bff3780ef0e7ba5313bf23644465644e19e6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 11:07:49 +0100 Subject: Unify associated function parsing. --- src/librustc_parse/parser/item.rs | 65 ++++++++++++++------------------------- src/libsyntax/ast.rs | 1 + 2 files changed, 24 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3fc4cafc0da..32cc156783c 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 dd8a7fa8665..5866f9db078 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. -- cgit 1.4.1-3-g733a5 From 63a9030e7b75312261733187f827df66db55cb1b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 11:30:04 +0100 Subject: 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(-) (limited to 'src') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 32cc156783c..3fbdbb4cb22 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 b3c1f60b7eb..ea21592997b 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 30ae6ed4c6d..d1e995013cb 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 70f55f0aeb9..6e20a9ce3c4 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 { -- cgit 1.4.1-3-g733a5 From fa828d7a0567cf833a8da9b10cc9936b3e9423dd Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 11:34:25 +0100 Subject: Relocate `is_const_item`. --- src/librustc_parse/parser/item.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3fbdbb4cb22..dbc0163eef6 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 ";" -- cgit 1.4.1-3-g733a5 From 404013e015d9a9f4835cda47e56aab5223f278ed Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 12:52:59 +0100 Subject: Leave a FIXME re. `allow_plus`. --- src/librustc_parse/parser/ty.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 84ffef68e9a..33d7c878e88 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, -- cgit 1.4.1-3-g733a5 From 34d91709b672d91ea9623ae4bc2275e8b003fc2c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 16:00:08 +0100 Subject: 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(-) (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 54ff1f56eec..e2c99f456e9 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 8c225b83f40..ca7c4ba8786 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 3cd4988ce0b..e4dff07e92c 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 dbc0163eef6..f391eda976c 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 5334fc485e7..aeba6dd2f67 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 33d7c878e88..1dffa6c94a8 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 f4b28077e9f..8be97155d8c 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 d63a9df8d9b..cc0f3c512f5 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 5866f9db078..d90d74d7a26 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 bb0462c19cd..97a85b0fe7e 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 03e394b8c7e..a141d4d71bb 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 7cc1a769e52..74df808b37e 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); } } } -- cgit 1.4.1-3-g733a5 From 9193d7a07e3c70f5f41c8a92aa34c120c9fdba0d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 16:15:10 +0100 Subject: Unify associated item pretty printing. --- src/libsyntax/print/pprust.rs | 96 ++++++++++--------------------------------- 1 file changed, 21 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a141d4d71bb..9e4615f60c0 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) { -- cgit 1.4.1-3-g733a5 From 76576d401c3fc33bab78cf022d0c4901d9b89548 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 16:58:37 +0100 Subject: 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(-) (limited to 'src') diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index ca7c4ba8786..026cb6eab1c 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 1e9203f377f..38ae7050abe 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 97a85b0fe7e..18d42f9dd66 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 9bfedb3b617..2eae6d494d0 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 6057be9826a..18acbf2cc13 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), } } -- cgit 1.4.1-3-g733a5 From c6c17e3e00273395869f7025f02c4be99c9f99b4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 17:00:20 +0100 Subject: Simplify `nt_to_tokenstream`. --- src/librustc_parse/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index faff386e923..58c36524380 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) => { -- cgit 1.4.1-3-g733a5 From 0d8a9d74e3bbeed1ad787e1b563e6884496728b2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 17:11:07 +0100 Subject: 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(-) (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e2c99f456e9..1ee02dcf0c1 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 f77523e6382..c3d2ed6b39c 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 7f72154e42c..e0ec9e62645 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 8be97155d8c..34534d6cca5 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 a5924efefc2..071ed0db870 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 d2d5a33ec7a..abed4b326a5 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 471e2634b8a..248027a91ab 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 33e24c8cfd4..682ddc421c2 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 f786de6401a..226719c7460 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 a64fec70961..14ca7a7eff3 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 74df808b37e..8fe8e136c10 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); } } -- cgit 1.4.1-3-g733a5 From 51ccdebe0b07f38e7e371a80424285539811c048 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 17:29:13 +0100 Subject: Unify associated item parsing more. --- src/librustc_parse/parser/item.rs | 49 ++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index f391eda976c..0126297a358 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, -- cgit 1.4.1-3-g733a5 From b499a88dfc484f077ec7264bd7fae7d7c60d9fb8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 02:03:31 +0100 Subject: 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 ++++++------ .../trait-item-with-defaultness-fail-semantic.rs | 2 ++ ...rait-item-with-defaultness-fail-semantic.stderr | 12 ++++---- 12 files changed, 56 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1ee02dcf0c1..e2c99f456e9 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 e0ec9e62645..7f72154e42c 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 34534d6cca5..ad6c99494a6 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 071ed0db870..a5924efefc2 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 abed4b326a5..d2d5a33ec7a 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 248027a91ab..471e2634b8a 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 226719c7460..c27fcb6a68e 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 14ca7a7eff3..3db9955d304 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 8fe8e136c10..e2c0ee61467 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 d9ebcdecb9b..1f61473c9d2 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 b67e30637aa..09f967f161e 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 48b502a1506..54111df3423 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() {} | ^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 0d41d0fe1423b4d21d6a9a2778419d399da1a13a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 02:38:33 +0100 Subject: 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 +++++++++++++++ src/test/ui/invalid/invalid-variadic-function.rs | 3 -- .../ui/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 ----- .../parser/variadic-ffi-semantic-restrictions.rs | 26 +++++++++++++++ .../variadic-ffi-semantic-restrictions.stderr | 38 ++++++++++++++++++++++ src/test/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 (limited to 'src') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 0126297a358..d4b62e8ebba 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 1dffa6c94a8..3ab290d1cbb 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 ad6c99494a6..a26c991c9cf 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 8d23f0e4770..00000000000 --- 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 7e58b17e7db..00000000000 --- 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 ce83cc87abe..00000000000 --- 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 aeeebdb9914..00000000000 --- 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 5f8b3f8f539..00000000000 --- 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 da83276c72d..00000000000 --- 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 00000000000..57086bca2f4 --- /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 00000000000..69244d92ee3 --- /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 00000000000..f8fcce6ba73 --- /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, ...); +} -- cgit 1.4.1-3-g733a5 From 3a57a2cca489da43fa3168aa1cb453e2b175a1f6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 02:53:18 +0100 Subject: `ast_validation`: move trait item logic to proper place. --- src/librustc_passes/ast_validation.rs | 43 +++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index a26c991c9cf..884af188ed6 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); } -- cgit 1.4.1-3-g733a5 From 35e9e097e7c7e977f36795c0febceb327e1fa33f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 03:16:12 +0100 Subject: 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 ++- .../c-variadic/variadic-ffi-no-fixed-args.stderr | 4 +- .../parser/variadic-ffi-semantic-restrictions.rs | 74 ++++++-- .../variadic-ffi-semantic-restrictions.stderr | 204 +++++++++++++++++++-- src/test/ui/parser/variadic-ffi-syntactic-pass.rs | 40 +++- 7 files changed, 322 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e2c99f456e9..58225e87f26 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 d4b62e8ebba..a7c98886622 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 884af188ed6..c75bd996e10 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 cb6060525fc..7af38c88f43 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 57086bca2f4..aa85f6d6b52 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 69244d92ee3..21992a29670 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 f8fcce6ba73..3875d6af137 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); } -- cgit 1.4.1-3-g733a5 From abf2e7aa959a4611bc2f607bc7e9200b8b81c089 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Dec 2019 00:08:09 +0100 Subject: 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(-) (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 58225e87f26..78df14adc5d 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 c3d2ed6b39c..f25714f741b 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 7f72154e42c..0fdd509a0bb 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 a8d88686679..0054f149f8c 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 026cb6eab1c..da8eae6028e 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 10b00d35d9b..8916fc08838 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 c75bd996e10..609885cb254 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 a5924efefc2..66ceb4212c8 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 d2d5a33ec7a..dc301375440 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 471e2634b8a..6e26553d82f 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 682ddc421c2..ad29fd9e1db 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 cc0f3c512f5..3b36c1c70f9 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 d90d74d7a26..1b729ebaf43 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 c27fcb6a68e..fcce9d4e95f 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 6f45211ac5f..263f8192241 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 a4449ca5b1d..2cfcbd3161f 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 2eae6d494d0..d4223af27ab 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 18acbf2cc13..22e99baae5b 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 d51fcf315a6..1c1fcc4f301 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, } } -- cgit 1.4.1-3-g733a5 From e52f902a8ab3a1abbb200607db4766d95b27bc8e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Dec 2019 00:13:59 +0100 Subject: `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(-) (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 78df14adc5d..50733512fae 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 f25714f741b..f0543b9057d 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 da8eae6028e..e84ac82942c 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 8916fc08838..1fc89961889 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 a7c98886622..0840a1551db 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 609885cb254..e90231f984b 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 dc301375440..e94e0dc695c 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 6e26553d82f..9bae339f80e 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 ad29fd9e1db..ec9c2a5b75d 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 3b36c1c70f9..df6ad51d104 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 1b729ebaf43..f7f84333857 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 fcce9d4e95f..871ec2c008e 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 18d42f9dd66..2a6cff5971c 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 9e4615f60c0..87f6ae85b69 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 e2c0ee61467..51e7fa1eb38 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 1c1fcc4f301..b7707bfb8e5 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, } } -- cgit 1.4.1-3-g733a5 From 74d4fbc5f5f68212d01a78738c207d5976fe13e4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Dec 2019 06:32:58 +0100 Subject: 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 ++++++++------- .../parser/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 (limited to 'src') diff --git a/src/librustc_error_codes/error_codes/E0743.md b/src/librustc_error_codes/error_codes/E0743.md index aaf19d8478c..1780fe59cbd 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 3ab290d1cbb..6f7ab0542d5 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 00000000000..9eeee195e56 --- /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 00000000000..8b9d676a45d --- /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`. -- cgit 1.4.1-3-g733a5 From 054458b48db87ce767d7cc3d2dd86846ada3e3da Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 11 Dec 2019 11:14:13 +0100 Subject: 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(-) (limited to 'src') diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index f0543b9057d..46c944fa678 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 ec9c2a5b75d..4321f62e03b 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 -- cgit 1.4.1-3-g733a5 From aa0ef5a01ff329daa822e7443ca7d6ae2bfc8476 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 16 Dec 2019 14:15:57 -0800 Subject: 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 ++++++++++++++++++ .../run-make/wasm-symbols-different-module/bar.rs | 33 ++++++++++++++++++++++ .../run-make/wasm-symbols-different-module/baz.rs | 22 +++++++++++++++ .../run-make/wasm-symbols-different-module/foo.rs | 23 +++++++++++++++ .../run-make/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 (limited to 'src') diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 1ea9362dc42..6779cce1f8a 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 c52c6cfa83c..922964ee45f 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 00000000000..bb6a5d3c9d2 --- /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 00000000000..7567060d781 --- /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 00000000000..fbb78619bb8 --- /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 00000000000..a4ba7e714cc --- /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 00000000000..ea3e0b4b2be --- /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 00000000000..7e9f90cf8bd --- /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'); +} -- cgit 1.4.1-3-g733a5 From 3a19fbf95d3b289f4c17aba910051cd9afd75887 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 23 Dec 2018 19:00:58 +0000 Subject: 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 +++++ src/librustc_mir/borrow_check/type_check/mod.rs | 49 +++------ src/librustc_mir/dataflow/move_paths/builder.rs | 1 + src/librustc_mir/interpret/step.rs | 2 +- src/librustc_mir/transform/add_retag.rs | 18 +--- src/librustc_mir/transform/check_consts/ops.rs | 17 ++++ src/librustc_mir/transform/check_consts/qualifs.rs | 18 ++-- .../transform/check_consts/validation.rs | 112 +++++++++++++-------- src/librustc_mir/transform/promote_consts.rs | 24 ++++- src/librustc_mir/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(-) (limited to 'src') diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ba8feb4ee73..3b4adbaf78c 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 445fa6ea8ca..a24b1d863d6 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 5d273fe85b6..fa96b51347d 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 bc12412312d..fca53db1475 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 6c627085b2e..7bcd9816786 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 5e13cabced0..5b21dfbdf1c 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 488ae8dbf90..3a8d782aa73 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 58fac5512d9..d5b9aaf9511 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 11012ef2fc7..2554d5e729d 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 663536bc2b4..108279eeef4 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 fa0864e0de7..5522da6fbf0 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 33ed69af6ba..33cdf1b27f8 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 dc21c674eea..0e4fe3f7f40 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 3df60993d9a..e5f3003cd71 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 223a5f8d605..28243bd71a2 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 6261315c711..0904264586c 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 4c723199102..4e5d8ae08fe 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 e2530795749..a61bff37fc8 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 68c2e16399a..01eebeb8c55 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 035ece23810..21ba02746c7 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), -- cgit 1.4.1-3-g733a5 From 35919ace7084e10fce15cb9bb42a9404b63b849d Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 20 Apr 2019 18:06:03 +0100 Subject: 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(-) (limited to 'src') diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index ddacda72e1e..15c7c92d7db 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 37eb0cc9d96..24282a6617a 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 270a1a64474..4d0039b2e8c 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 07a44b190b2..6b33e8433f6 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 8c852854be1..6cbc25aa735 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 47644d9ba83..46e0d2a17b3 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 00a6b26d0cf..096f98bade2 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 3f82b81a47d..3c8c0ff4493 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 32995448a21..ccecaeac96b 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 8130f4dedc9..1aed218aeb4 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 30f8459c2e1..15d94ab69d8 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`. -- cgit 1.4.1-3-g733a5 From 5fb797ca753dfc5586ac277d5af4facab8c7c22f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 20 Apr 2019 18:06:10 +0100 Subject: 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(-) (limited to 'src') diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 67e5bfafafd..4f482431d33 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 f270dec5fe2..5a37b67229c 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; -- cgit 1.4.1-3-g733a5 From 7081c79b7eed2c5b36674526d00c604b647027a3 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 20 Apr 2019 18:07:46 +0100 Subject: 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 (limited to 'src') diff --git a/src/test/mir-opt/address-of.rs b/src/test/mir-opt/address-of.rs new file mode 100644 index 00000000000..bbd1ca68a86 --- /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 -- cgit 1.4.1-3-g733a5 From 7b0cc6a439d2cf7a9d6dab5b1df2772488cc80a8 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 17 Sep 2019 19:32:40 +0100 Subject: 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 (limited to 'src') 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 00000000000..8ab011661e3 --- /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; +} -- cgit 1.4.1-3-g733a5 From 15931947f59e0010b73469711cb811f09aaf0cdd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 17 Sep 2019 21:18:15 +0100 Subject: Update test now that reference to pointer casts have more checks --- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 15 ++++++- src/test/ui/consts/const-eval/ub-wide-ptr.stderr | 54 +++++++++++++++--------- 2 files changed, 46 insertions(+), 23 deletions(-) (limited to 'src') 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 1f810c40572..a5c2a57c6c8 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 85fb8ac2a4a..ce57d680dc9 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`. -- cgit 1.4.1-3-g733a5 From 6dcc78997f19822373ed17549004282da82851dc Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 18 Sep 2019 21:31:25 +0100 Subject: Add more tests for raw_ref_op --- src/librustc_error_codes/error_codes/E0745.md | 2 +- src/test/pretty/raw-address-of.rs | 12 ++++ .../ui/borrowck/borrow-raw-address-of-borrowed.rs | 22 +++++++ .../borrowck/borrow-raw-address-of-borrowed.stderr | 40 ++++++++++++ .../borrow-raw-address-of-deref-mutability-ok.rs | 23 +++++++ .../borrow-raw-address-of-deref-mutability.rs | 17 +++++ .../borrow-raw-address-of-deref-mutability.stderr | 21 ++++++ .../borrow-raw-address-of-mutability-ok.rs | 44 +++++++++++++ .../borrowck/borrow-raw-address-of-mutability.rs | 42 ++++++++++++ .../borrow-raw-address-of-mutability.stderr | 59 +++++++++++++++++ .../ui/consts/const-address-of-interior-mut.rs | 16 +++++ .../ui/consts/const-address-of-interior-mut.stderr | 27 ++++++++ src/test/ui/consts/const-address-of-mut.rs | 14 ++++ src/test/ui/consts/const-address-of-mut.stderr | 39 ++++++++++++ src/test/ui/consts/const-address-of.rs | 19 ++++++ .../consts/const-mut-refs/const_mut_address_of.rs | 30 +++++++++ src/test/ui/consts/min_const_fn/address_of.rs | 17 +++++ src/test/ui/consts/min_const_fn/address_of.stderr | 21 ++++++ .../ui/consts/min_const_fn/address_of_const.rs | 19 ++++++ src/test/ui/lint/lint-unused-mut-variables.rs | 8 ++- src/test/ui/lint/lint-unused-mut-variables.stderr | 14 +++- .../ui/packed/packed-struct-address-of-element.rs | 37 +++++++++++ src/test/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 +++--- src/test/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 ++++----- src/test/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 (limited to 'src') diff --git a/src/librustc_error_codes/error_codes/E0745.md b/src/librustc_error_codes/error_codes/E0745.md index 39bebdcd375..6595691ce78 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 00000000000..6ccc434a1e7 --- /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 00000000000..f25fd7f66b3 --- /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 00000000000..ff461b748be --- /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 00000000000..e381384fe65 --- /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 00000000000..712873528b5 --- /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 00000000000..31af38507c7 --- /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 00000000000..e1cf2dc5386 --- /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 00000000000..320c54b806a --- /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 00000000000..cf01c362d50 --- /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 00000000000..60c7c31daca --- /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 00000000000..f15174c33b3 --- /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 00000000000..fe9188cb490 --- /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 00000000000..15f2296c42c --- /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 00000000000..ba162f2a2ba --- /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 00000000000..130ba9283b1 --- /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 00000000000..f8506d70b24 --- /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 00000000000..3554b8112b1 --- /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 00000000000..3db19e9cde8 --- /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 1af44ecf362..dd8dbda6d43 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 92c2b68652d..c1ab0ab33d4 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 00000000000..812d23fb580 --- /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 6ac42ed0d47..0072b6191eb 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 de847909eb3..0c6e23a00d5 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 04c59c95fca..00000000000 --- 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 d251586de55..a814003aebf 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 b0bfc74903b..00000000000 --- 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 ac2445f049c..32df56468da 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 de070733735..80dea76d595 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 f0a6bcce2ac..6bf37408a8b 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 3fae5db3d51..00000000000 --- 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 - -- cgit 1.4.1-3-g733a5 From a74911662e8de2c024ea188e4dcac6a494c74455 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 2 Dec 2019 22:20:35 +0000 Subject: Fix comment ordering --- src/libsyntax/ast.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 92ba071a03d..274e19ec3e4 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, } -- cgit 1.4.1-3-g733a5