Skip to content

Rollup of 7 pull requests #63025

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 29 commits into from
Closed
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bd7be36
Allow lifetime elision in `Pin<&(mut) Self>`
taiki-e May 26, 2019
a9a50bc
Remove query for `.pin_type()`
taiki-e May 27, 2019
0bc8878
Make is_self_ty a method on SelfVisitor
taiki-e May 29, 2019
3be8422
Use Set1<Region> instead of Option<Region>
taiki-e May 29, 2019
76794f1
add a bevy of new test cases
nikomatsakis Jun 28, 2019
6018c46
Update src/test/ui/self/elision/README.md
taiki-e Jul 15, 2019
78d2129
Add main functions and check-pass annotations
taiki-e Jul 15, 2019
044d4bb
Minor clean up
taiki-e Jul 15, 2019
d79d13f
Add test for multiple ref-self
taiki-e Jul 15, 2019
44bf6b6
tests: Add minimal reproduction of #61963.
davidtwco Jul 20, 2019
4242206
Re-enable assertions in PPC dist builder
mati865 Jul 19, 2019
c7a599e
bump crossbeam-epoch dependency
RalfJung Jul 25, 2019
eb4fbda
Simplify save-analysis JSON dumper interface
Mark-Simulacrum Jul 25, 2019
68c0ba2
Rename JsonDumper to Dumper
Mark-Simulacrum Jul 25, 2019
7369c17
Add tests for `self: (&)AssocType`
taiki-e Jul 26, 2019
e995523
Break dependencies between `syntax_ext` and some other crates
petrochenkov Jul 17, 2019
a0fb9c9
Move proc macro server into libsyntax
petrochenkov Jul 18, 2019
11137c6
Move test harness generation into libsyntax_ext
petrochenkov Jul 18, 2019
0c0ddcd
Move standard library injection into libsyntax_ext
petrochenkov Jul 18, 2019
0a24e28
syntax_ext: `proc_macro_decls` -> `proc_macro_harness`
petrochenkov Jul 18, 2019
d7b2110
add repr(transparent) to IoSliceMut where missing
nivkner Jul 26, 2019
cae8680
lowering: Omit bare trait lint on macro call sites
davidtwco Jul 26, 2019
7811ae8
Rollup merge of #61207 - taiki-e:arbitrary_self_types-lifetime-elisio…
Centril Jul 26, 2019
01d7e7a
Rollup merge of #62771 - petrochenkov:depext, r=eddyb
Centril Jul 26, 2019
394f049
Rollup merge of #62949 - mati865:patch-1, r=alexcrichton
Centril Jul 26, 2019
75d3a29
Rollup merge of #62974 - RalfJung:crossbeam, r=alexcrichton
Centril Jul 26, 2019
b3e2164
Rollup merge of #62979 - Mark-Simulacrum:json-dumper-pretty, r=Xanewok
Centril Jul 26, 2019
0ae4151
Rollup merge of #63013 - nivkner:ffi-safe-slice, r=sfackler
Centril Jul 26, 2019
f12327b
Rollup merge of #63014 - davidtwco:rustfix-incorrect-dyn-suggestion, …
Centril Jul 26, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -590,7 +590,7 @@ name = "crossbeam-deque"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
]

@@ -610,15 +610,15 @@ dependencies = [

[[package]]
name = "crossbeam-epoch"
version = "0.7.0"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
@@ -1671,6 +1671,14 @@ name = "memoffset"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "memoffset"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "mime"
version = "0.3.13"
@@ -2863,31 +2871,20 @@ dependencies = [
name = "rustc_driver"
version = "0.0.0"
dependencies = [
"arena 0.0.0",
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_ast_borrowck 0.0.0",
"rustc_codegen_utils 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_incremental 0.0.0",
"rustc_interface 0.0.0",
"rustc_lint 0.0.0",
"rustc_metadata 0.0.0",
"rustc_mir 0.0.0",
"rustc_passes 0.0.0",
"rustc_plugin 0.0.0",
"rustc_privacy 0.0.0",
"rustc_resolve 0.0.0",
"rustc_save_analysis 0.0.0",
"rustc_target 0.0.0",
"rustc_traits 0.0.0",
"rustc_typeck 0.0.0",
"serialize 0.0.0",
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
@@ -3019,7 +3016,6 @@ dependencies = [
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"syntax_ext 0.0.0",
"syntax_pos 0.0.0",
]

@@ -3064,9 +3060,7 @@ dependencies = [
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_mir 0.0.0",
"syntax 0.0.0",
"syntax_ext 0.0.0",
"syntax_pos 0.0.0",
]

@@ -3312,6 +3306,11 @@ name = "scopeguard"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "scopeguard"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "security-framework"
version = "0.3.1"
@@ -4330,7 +4329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c"
"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
@@ -4440,6 +4439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425"
"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed"
"checksum minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "4c909e78edf61f3aa0dd2086da168cdf304329044bbf248768ca3d20253ec8c0"
@@ -4542,6 +4542,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2"
"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
4 changes: 0 additions & 4 deletions src/ci/docker/dist-powerpc-linux/Dockerfile
Original file line number Diff line number Diff line change
@@ -36,7 +36,3 @@ ENV HOSTS=powerpc-unknown-linux-gnu

ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS

# FIXME(#36150) this will fail the bootstrap. Probably means something bad is
# happening!
ENV NO_LLVM_ASSERTIONS 1
25 changes: 16 additions & 9 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
@@ -63,7 +63,6 @@ use syntax::errors;
use syntax::ext::hygiene::ExpnId;
use syntax::print::pprust;
use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned};
use syntax::std_inject;
use syntax::symbol::{kw, sym, Symbol};
use syntax::tokenstream::{TokenStream, TokenTree};
use syntax::parse::token::{self, Token};
@@ -241,7 +240,7 @@ pub fn lower_crate(
dep_graph.assert_ignored();

LoweringContext {
crate_root: std_inject::injected_crate_name().map(Symbol::intern),
crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
sess,
cstore,
resolver,
@@ -5754,13 +5753,21 @@ impl<'a> LoweringContext<'a> {
}

fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) {
self.sess.buffer_lint_with_diagnostic(
builtin::BARE_TRAIT_OBJECTS,
id,
span,
"trait objects without an explicit `dyn` are deprecated",
builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
)
// FIXME(davidtwco): This is a hack to detect macros which produce spans of the
// call site which do not have a macro backtrace. See #61963.
let is_macro_callsite = self.sess.source_map()
.span_to_snippet(span)
.map(|snippet| snippet.starts_with("#["))
.unwrap_or(true);
if !is_macro_callsite {
self.sess.buffer_lint_with_diagnostic(
builtin::BARE_TRAIT_OBJECTS,
id,
span,
"trait objects without an explicit `dyn` are deprecated",
builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
)
}
}

fn wrap_in_try_constructor(
95 changes: 62 additions & 33 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
@@ -2146,48 +2146,77 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// First (determined here), if `self` is by-reference, then the
// implied output region is the region of the self parameter.
if has_self {
// Look for `self: &'a Self` - also desugared from `&'a self`,
// and if that matches, use it for elision and return early.
let is_self_ty = |res: Res| {
if let Res::SelfTy(..) = res {
return true;
}

// Can't always rely on literal (or implied) `Self` due
// to the way elision rules were originally specified.
let impl_self = impl_self.map(|ty| &ty.node);
if let Some(&hir::TyKind::Path(hir::QPath::Resolved(None, ref path))) = impl_self {
match path.res {
// Whitelist the types that unambiguously always
// result in the same type constructor being used
// (it can't differ between `Self` and `self`).
Res::Def(DefKind::Struct, _)
| Res::Def(DefKind::Union, _)
| Res::Def(DefKind::Enum, _)
| Res::PrimTy(_) => {
return res == path.res
struct SelfVisitor<'a> {
map: &'a NamedRegionMap,
impl_self: Option<&'a hir::TyKind>,
lifetime: Set1<Region>,
}

impl SelfVisitor<'_> {
// Look for `self: &'a Self` - also desugared from `&'a self`,
// and if that matches, use it for elision and return early.
fn is_self_ty(&self, res: Res) -> bool {
if let Res::SelfTy(..) = res {
return true;
}

// Can't always rely on literal (or implied) `Self` due
// to the way elision rules were originally specified.
if let Some(&hir::TyKind::Path(hir::QPath::Resolved(None, ref path))) =
self.impl_self
{
match path.res {
// Whitelist the types that unambiguously always
// result in the same type constructor being used
// (it can't differ between `Self` and `self`).
Res::Def(DefKind::Struct, _)
| Res::Def(DefKind::Union, _)
| Res::Def(DefKind::Enum, _)
| Res::PrimTy(_) => {
return res == path.res
}
_ => {}
}
_ => {}
}

false
}
}

false
};
impl<'a> Visitor<'a> for SelfVisitor<'a> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
NestedVisitorMap::None
}

if let hir::TyKind::Rptr(lifetime_ref, ref mt) = inputs[0].node {
if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.node {
if is_self_ty(path.res) {
if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
let scope = Scope::Elision {
elide: Elide::Exact(lifetime),
s: self.scope,
};
self.with(scope, |_, this| this.visit_ty(output));
return;
fn visit_ty(&mut self, ty: &'a hir::Ty) {
if let hir::TyKind::Rptr(lifetime_ref, ref mt) = ty.node {
if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.node
{
if self.is_self_ty(path.res) {
if let Some(lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
self.lifetime.insert(*lifetime);
}
}
}
}
intravisit::walk_ty(self, ty)
}
}

let mut visitor = SelfVisitor {
map: self.map,
impl_self: impl_self.map(|ty| &ty.node),
lifetime: Set1::Empty,
};
visitor.visit_ty(&inputs[0]);
if let Set1::One(lifetime) = visitor.lifetime {
let scope = Scope::Elision {
elide: Elide::Exact(lifetime),
s: self.scope,
};
self.with(scope, |_, this| this.visit_ty(output));
return;
}
}

// Second, if there was exactly one lifetime (either a substitution or a
11 changes: 0 additions & 11 deletions src/librustc_driver/Cargo.toml
Original file line number Diff line number Diff line change
@@ -10,30 +10,19 @@ path = "lib.rs"
crate-type = ["dylib"]

[dependencies]
arena = { path = "../libarena" }
graphviz = { path = "../libgraphviz" }
log = "0.4"
env_logger = { version = "0.5", default-features = false }
rayon = { version = "0.2.0", package = "rustc-rayon" }
rustc = { path = "../librustc" }
rustc_target = { path = "../librustc_target" }
rustc_ast_borrowck = { path = "../librustc_ast_borrowck" }
rustc_data_structures = { path = "../librustc_data_structures" }
errors = { path = "../librustc_errors", package = "rustc_errors" }
rustc_incremental = { path = "../librustc_incremental" }
rustc_lint = { path = "../librustc_lint" }
rustc_metadata = { path = "../librustc_metadata" }
rustc_mir = { path = "../librustc_mir" }
rustc_passes = { path = "../librustc_passes" }
rustc_plugin = { path = "../librustc_plugin" }
rustc_privacy = { path = "../librustc_privacy" }
rustc_resolve = { path = "../librustc_resolve" }
rustc_save_analysis = { path = "../librustc_save_analysis" }
rustc_traits = { path = "../librustc_traits" }
rustc_codegen_utils = { path = "../librustc_codegen_utils" }
rustc_typeck = { path = "../librustc_typeck" }
rustc_interface = { path = "../librustc_interface" }
rustc_serialize = { path = "../libserialize", package = "serialize" }
syntax = { path = "../libsyntax" }
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
syntax_pos = { path = "../libsyntax_pos" }
11 changes: 8 additions & 3 deletions src/librustc_interface/passes.rs
Original file line number Diff line number Diff line change
@@ -278,7 +278,12 @@ pub fn register_plugins<'a>(

krate = time(sess, "crate injection", || {
let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s);
syntax::std_inject::maybe_inject_crates_ref(krate, alt_std_name, sess.edition())
let (krate, name) =
syntax_ext::standard_library_imports::inject(krate, alt_std_name, sess.edition());
if let Some(name) = name {
sess.parse_sess.injected_crate_name.set(name);
}
krate
});

let registrars = time(sess, "plugin loading", || {
@@ -453,7 +458,7 @@ fn configure_and_expand_inner<'a>(
sess.profiler(|p| p.end_activity("macro expansion"));

time(sess, "maybe building test harness", || {
syntax::test::modify_for_testing(
syntax_ext::test_harness::inject(
&sess.parse_sess,
&mut resolver,
sess.opts.test,
@@ -482,7 +487,7 @@ fn configure_and_expand_inner<'a>(
let num_crate_types = crate_types.len();
let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro);
let is_test_crate = sess.opts.test;
syntax_ext::proc_macro_decls::modify(
syntax_ext::proc_macro_harness::inject(
&sess.parse_sess,
&mut resolver,
krate,
1 change: 0 additions & 1 deletion src/librustc_metadata/Cargo.toml
Original file line number Diff line number Diff line change
@@ -21,5 +21,4 @@ rustc_target = { path = "../librustc_target" }
rustc_serialize = { path = "../libserialize", package = "serialize" }
stable_deref_trait = "1.0.0"
syntax = { path = "../libsyntax" }
syntax_ext = { path = "../libsyntax_ext" }
syntax_pos = { path = "../libsyntax_pos" }
3 changes: 1 addition & 2 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
@@ -586,8 +586,7 @@ impl<'a> CrateLoader<'a> {
use std::{env, mem};
use crate::dynamic_lib::DynamicLibrary;
use proc_macro::bridge::client::ProcMacro;
use syntax_ext::deriving::custom::ProcMacroDerive;
use syntax_ext::proc_macro_impl::{AttrProcMacro, BangProcMacro};
use syntax::ext::proc_macro::{BangProcMacro, AttrProcMacro, ProcMacroDerive};

let path = match dylib {
Some(dylib) => dylib,
2 changes: 1 addition & 1 deletion src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
@@ -31,10 +31,10 @@ use syntax::attr;
use syntax::source_map;
use syntax::edition::Edition;
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
use syntax::ext::proc_macro::BangProcMacro;
use syntax::parse::source_file_to_stream;
use syntax::parse::parser::emit_unclosed_delims;
use syntax::symbol::{Symbol, sym};
use syntax_ext::proc_macro_impl::BangProcMacro;
use syntax_pos::{Span, NO_EXPANSION, FileName};
use rustc_data_structures::bit_set::BitSet;

2 changes: 0 additions & 2 deletions src/librustc_passes/Cargo.toml
Original file line number Diff line number Diff line change
@@ -11,9 +11,7 @@ path = "lib.rs"
[dependencies]
log = "0.4"
rustc = { path = "../librustc" }
rustc_mir = { path = "../librustc_mir"}
rustc_data_structures = { path = "../librustc_data_structures" }
syntax = { path = "../libsyntax" }
syntax_ext = { path = "../libsyntax_ext" }
syntax_pos = { path = "../libsyntax_pos" }
errors = { path = "../librustc_errors", package = "rustc_errors" }
2 changes: 1 addition & 1 deletion src/librustc_passes/ast_validation.rs
Original file line number Diff line number Diff line change
@@ -14,12 +14,12 @@ use rustc::session::Session;
use rustc_data_structures::fx::FxHashMap;
use syntax::ast::*;
use syntax::attr;
use syntax::ext::proc_macro::is_proc_macro_attr;
use syntax::feature_gate::is_builtin_attr;
use syntax::source_map::Spanned;
use syntax::symbol::{kw, sym};
use syntax::visit::{self, Visitor};
use syntax::{span_err, struct_span_err, walk_list};
use syntax_ext::proc_macro_decls::is_proc_macro_attr;
use syntax_pos::{Span, MultiSpan};
use errors::{Applicability, FatalError};

7 changes: 4 additions & 3 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
@@ -35,7 +35,6 @@ use syntax::ext::tt::macro_rules;
use syntax::feature_gate::is_builtin_attr;
use syntax::parse::token::{self, Token};
use syntax::span_err;
use syntax::std_inject::injected_crate_name;
use syntax::symbol::{kw, sym};
use syntax::visit::{self, Visitor};

@@ -368,8 +367,10 @@ impl<'a> Resolver<'a> {
};

self.populate_module_if_necessary(module);
if injected_crate_name().map_or(false, |name| ident.name.as_str() == name) {
self.injected_crate = Some(module);
if let Some(name) = self.session.parse_sess.injected_crate_name.try_get() {
if name.as_str() == ident.name.as_str() {
self.injected_crate = Some(module);
}
}

let used = self.process_legacy_macro_imports(item, module, &parent_scope);
20 changes: 10 additions & 10 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
//!
//! SpanUtils is used to manipulate spans. In particular, to extract sub-spans
//! from spans (e.g., the span for `bar` from the above example path).
//! DumpVisitor walks the AST and processes it, and JsonDumper is used for
//! DumpVisitor walks the AST and processes it, and Dumper is used for
//! recording the output.
use rustc::hir::def::{Res, DefKind as HirDefKind};
@@ -38,7 +38,7 @@ use syntax_pos::*;

use crate::{escape, generated_code, id_from_def_id, id_from_node_id, lower_attributes,
PathCollector, SaveContext};
use crate::json_dumper::{Access, DumpOutput, JsonDumper};
use crate::dumper::{Access, Dumper};
use crate::span_utils::SpanUtils;
use crate::sig;

@@ -75,10 +75,10 @@ macro_rules! access_from_vis {
};
}

pub struct DumpVisitor<'l, 'tcx, 'll, O: DumpOutput> {
pub struct DumpVisitor<'l, 'tcx, 'll> {
save_ctxt: SaveContext<'l, 'tcx>,
tcx: TyCtxt<'tcx>,
dumper: &'ll mut JsonDumper<O>,
dumper: &'ll mut Dumper,

span: SpanUtils<'l>,

@@ -92,11 +92,11 @@ pub struct DumpVisitor<'l, 'tcx, 'll, O: DumpOutput> {
// macro_calls: FxHashSet<Span>,
}

impl<'l, 'tcx, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
impl<'l, 'tcx, 'll> DumpVisitor<'l, 'tcx, 'll> {
pub fn new(
save_ctxt: SaveContext<'l, 'tcx>,
dumper: &'ll mut JsonDumper<O>,
) -> DumpVisitor<'l, 'tcx, 'll, O> {
dumper: &'ll mut Dumper,
) -> DumpVisitor<'l, 'tcx, 'll> {
let span_utils = SpanUtils::new(&save_ctxt.tcx.sess);
DumpVisitor {
tcx: save_ctxt.tcx,
@@ -111,7 +111,7 @@ impl<'l, 'tcx, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {

fn nest_scope<F>(&mut self, scope_id: NodeId, f: F)
where
F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>),
F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll>),
{
let parent_scope = self.cur_scope;
self.cur_scope = scope_id;
@@ -121,7 +121,7 @@ impl<'l, 'tcx, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {

fn nest_tables<F>(&mut self, item_id: NodeId, f: F)
where
F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>),
F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll>),
{
let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id);
if self.tcx.has_typeck_tables(item_def_id) {
@@ -1311,7 +1311,7 @@ impl<'l, 'tcx, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
}
}

impl<'l, 'tcx, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, O> {
impl<'l, 'tcx, 'll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll> {
fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], id: NodeId) {
// Since we handle explicit modules ourselves in visit_item, this should
// only get called for the root module of a crate.
Original file line number Diff line number Diff line change
@@ -1,80 +1,33 @@
use std::io::Write;

use rls_data::config::Config;
use rls_data::{self, Analysis, CompilationOptions, CratePreludeData, Def, DefKind, Impl, Import,
MacroRef, Ref, RefKind, Relation};
use rls_span::{Column, Row};

use log::error;

#[derive(Debug)]
pub struct Access {
pub reachable: bool,
pub public: bool,
}

pub struct JsonDumper<O: DumpOutput> {
pub struct Dumper {
result: Analysis,
config: Config,
output: O,
}

pub trait DumpOutput {
fn dump(&mut self, result: &Analysis);
}

pub struct WriteOutput<'b, W: Write> {
output: &'b mut W,
}

impl<'b, W: Write> DumpOutput for WriteOutput<'b, W> {
fn dump(&mut self, result: &Analysis) {
if let Err(e) = serde_json::to_writer(self.output.by_ref(), result) {
error!("Can't serialize save-analysis: {:?}", e);
}
}
}

pub struct CallbackOutput<'b> {
callback: &'b mut dyn FnMut(&Analysis),
}

impl<'b> DumpOutput for CallbackOutput<'b> {
fn dump(&mut self, result: &Analysis) {
(self.callback)(result)
}
}

impl<'b, W: Write> JsonDumper<WriteOutput<'b, W>> {
pub fn new(writer: &'b mut W, config: Config) -> JsonDumper<WriteOutput<'b, W>> {
JsonDumper {
output: WriteOutput { output: writer },
impl Dumper {
pub fn new(config: Config) -> Dumper {
Dumper {
config: config.clone(),
result: Analysis::new(config),
}
}
}

impl<'b> JsonDumper<CallbackOutput<'b>> {
pub fn with_callback(
callback: &'b mut dyn FnMut(&Analysis),
config: Config,
) -> JsonDumper<CallbackOutput<'b>> {
JsonDumper {
output: CallbackOutput { callback },
config: config.clone(),
result: Analysis::new(config),
}
}
}

impl<O: DumpOutput> Drop for JsonDumper<O> {
fn drop(&mut self) {
self.output.dump(&self.result);
pub fn to_output(self, f: impl FnOnce(&Analysis)) {
f(&self.result)
}
}

impl<'b, O: DumpOutput + 'b> JsonDumper<O> {
impl Dumper {
pub fn crate_prelude(&mut self, data: CratePreludeData) {
self.result.prelude = Some(data)
}
32 changes: 18 additions & 14 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
#![recursion_limit="256"]


mod json_dumper;
mod dumper;
mod dump_visitor;
#[macro_use]
mod span_utils;
@@ -39,7 +39,7 @@ use syntax::visit::{self, Visitor};
use syntax::print::pprust::{arg_to_string, ty_to_string};
use syntax_pos::*;

use json_dumper::JsonDumper;
use dumper::Dumper;
use dump_visitor::DumpVisitor;
use span_utils::SpanUtils;

@@ -1075,17 +1075,19 @@ impl<'a> SaveHandler for DumpHandler<'a> {
input: &'l Input,
) {
let sess = &save_ctxt.tcx.sess;
let file_name = {
let (mut output, file_name) = self.output_file(&save_ctxt);
let mut dumper = JsonDumper::new(&mut output, save_ctxt.config.clone());
let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
let (output, file_name) = self.output_file(&save_ctxt);
let mut dumper = Dumper::new(save_ctxt.config.clone());
let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);

visitor.dump_crate_info(cratename, krate);
visitor.dump_compilation_options(input, cratename);
visit::walk_crate(&mut visitor, krate);
visitor.dump_crate_info(cratename, krate);
visitor.dump_compilation_options(input, cratename);
visit::walk_crate(&mut visitor, krate);

file_name
};
dumper.to_output(|analysis| {
if let Err(e) = serde_json::to_writer(output, analysis) {
error!("Can't serialize save-analysis: {:?}", e);
}
});

if sess.opts.debugging_opts.emit_artifact_notifications {
sess.parse_sess.span_diagnostic
@@ -1107,17 +1109,19 @@ impl<'b> SaveHandler for CallbackHandler<'b> {
cratename: &str,
input: &'l Input,
) {
// We're using the JsonDumper here because it has the format of the
// We're using the Dumper here because it has the format of the
// save-analysis results that we will pass to the callback. IOW, we are
// using the JsonDumper to collect the save-analysis results, but not
// using the Dumper to collect the save-analysis results, but not
// actually to dump them to a file. This is all a bit convoluted and
// there is certainly a simpler design here trying to get out (FIXME).
let mut dumper = JsonDumper::with_callback(self.callback, save_ctxt.config.clone());
let mut dumper = Dumper::new(save_ctxt.config.clone());
let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);

visitor.dump_crate_info(cratename, krate);
visitor.dump_compilation_options(input, cratename);
visit::walk_crate(&mut visitor, krate);

dumper.to_output(|a| (self.callback)(a))
}
}

1 change: 1 addition & 0 deletions src/libstd/sys/unix/io.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ impl<'a> IoSlice<'a> {
}
}

#[repr(transparent)]
pub struct IoSliceMut<'a> {
vec: iovec,
_p: PhantomData<&'a mut [u8]>,
1 change: 1 addition & 0 deletions src/libstd/sys/wasi/io.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ impl<'a> IoSlice<'a> {
}
}

#[repr(transparent)]
pub struct IoSliceMut<'a> {
vec: __wasi_iovec_t,
_p: PhantomData<&'a mut [u8]>,
1 change: 1 addition & 0 deletions src/libstd/sys/windows/io.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ impl<'a> IoSlice<'a> {
}
}

#[repr(transparent)]
pub struct IoSliceMut<'a> {
vec: c::WSABUF,
_p: PhantomData<&'a mut [u8]>,
4 changes: 2 additions & 2 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::ast::{self, Attribute, Name, PatKind};
use crate::attr::{HasAttrs, Stability, Deprecation};
use crate::source_map::{SourceMap, Spanned, FileName, respan};
use crate::source_map::{SourceMap, Spanned, respan};
use crate::edition::Edition;
use crate::ext::expand::{self, AstFragment, Invocation};
use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency};
@@ -14,7 +14,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree};

use errors::{DiagnosticBuilder, DiagnosticId};
use smallvec::{smallvec, SmallVec};
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP};
use syntax_pos::hygiene::{ExpnInfo, ExpnKind};

use rustc_data_structures::fx::FxHashMap;
72 changes: 0 additions & 72 deletions src/libsyntax/ext/derive.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ use crate::attr::{self, HasAttrs};
use crate::source_map::{dummy_spanned, respan};
use crate::config::StripUnconfigured;
use crate::ext::base::*;
use crate::ext::derive::{add_derived_markers, collect_derives};
use crate::ext::proc_macro::{add_derived_markers, collect_derives};
use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind};
use crate::ext::placeholders::{placeholder, PlaceholderExpander};
use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
249 changes: 249 additions & 0 deletions src/libsyntax/ext/proc_macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
use crate::ast::{self, ItemKind, Attribute, Mac};
use crate::attr::{mark_used, mark_known, HasAttrs};
use crate::errors::{Applicability, FatalError};
use crate::ext::base::{self, *};
use crate::ext::build::AstBuilder;
use crate::ext::proc_macro_server;
use crate::parse::{self, token};
use crate::parse::parser::PathStyle;
use crate::symbol::{sym, Symbol};
use crate::tokenstream::{self, TokenStream};
use crate::visit::Visitor;

use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
use syntax_pos::hygiene::{ExpnInfo, ExpnKind};
use syntax_pos::{Span, DUMMY_SP};

const EXEC_STRATEGY: proc_macro::bridge::server::SameThread =
proc_macro::bridge::server::SameThread;

pub struct BangProcMacro {
pub client: proc_macro::bridge::client::Client<
fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
>,
}

impl base::ProcMacro for BangProcMacro {
fn expand<'cx>(&self,
ecx: &'cx mut ExtCtxt<'_>,
span: Span,
input: TokenStream)
-> TokenStream {
let server = proc_macro_server::Rustc::new(ecx);
match self.client.run(&EXEC_STRATEGY, server, input) {
Ok(stream) => stream,
Err(e) => {
let msg = "proc macro panicked";
let mut err = ecx.struct_span_fatal(span, msg);
if let Some(s) = e.as_str() {
err.help(&format!("message: {}", s));
}

err.emit();
FatalError.raise();
}
}
}
}

pub struct AttrProcMacro {
pub client: proc_macro::bridge::client::Client<
fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream,
>,
}

impl base::AttrProcMacro for AttrProcMacro {
fn expand<'cx>(&self,
ecx: &'cx mut ExtCtxt<'_>,
span: Span,
annotation: TokenStream,
annotated: TokenStream)
-> TokenStream {
let server = proc_macro_server::Rustc::new(ecx);
match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) {
Ok(stream) => stream,
Err(e) => {
let msg = "custom attribute panicked";
let mut err = ecx.struct_span_fatal(span, msg);
if let Some(s) = e.as_str() {
err.help(&format!("message: {}", s));
}

err.emit();
FatalError.raise();
}
}
}
}

pub struct ProcMacroDerive {
pub client: proc_macro::bridge::client::Client<
fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
>,
pub attrs: Vec<ast::Name>,
}

impl MultiItemModifier for ProcMacroDerive {
fn expand(&self,
ecx: &mut ExtCtxt<'_>,
span: Span,
_meta_item: &ast::MetaItem,
item: Annotatable)
-> Vec<Annotatable> {
let item = match item {
Annotatable::Item(item) => item,
Annotatable::ImplItem(_) |
Annotatable::TraitItem(_) |
Annotatable::ForeignItem(_) |
Annotatable::Stmt(_) |
Annotatable::Expr(_) => {
ecx.span_err(span, "proc-macro derives may only be \
applied to a struct, enum, or union");
return Vec::new()
}
};
match item.node {
ItemKind::Struct(..) |
ItemKind::Enum(..) |
ItemKind::Union(..) => {},
_ => {
ecx.span_err(span, "proc-macro derives may only be \
applied to a struct, enum, or union");
return Vec::new()
}
}

// Mark attributes as known, and used.
MarkAttrs(&self.attrs).visit_item(&item);

let token = token::Interpolated(Lrc::new(token::NtItem(item)));
let input = tokenstream::TokenTree::token(token, DUMMY_SP).into();

let server = proc_macro_server::Rustc::new(ecx);
let stream = match self.client.run(&EXEC_STRATEGY, server, input) {
Ok(stream) => stream,
Err(e) => {
let msg = "proc-macro derive panicked";
let mut err = ecx.struct_span_fatal(span, msg);
if let Some(s) = e.as_str() {
err.help(&format!("message: {}", s));
}

err.emit();
FatalError.raise();
}
};

let error_count_before = ecx.parse_sess.span_diagnostic.err_count();
let msg = "proc-macro derive produced unparseable tokens";

let mut parser = parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive"));
let mut items = vec![];

loop {
match parser.parse_item() {
Ok(None) => break,
Ok(Some(item)) => {
items.push(Annotatable::Item(item))
}
Err(mut err) => {
// FIXME: handle this better
err.cancel();
ecx.struct_span_fatal(span, msg).emit();
FatalError.raise();
}
}
}


// fail if there have been errors emitted
if ecx.parse_sess.span_diagnostic.err_count() > error_count_before {
ecx.struct_span_fatal(span, msg).emit();
FatalError.raise();
}

items
}
}

struct MarkAttrs<'a>(&'a [ast::Name]);

impl<'a> Visitor<'a> for MarkAttrs<'a> {
fn visit_attribute(&mut self, attr: &Attribute) {
if let Some(ident) = attr.ident() {
if self.0.contains(&ident.name) {
mark_used(attr);
mark_known(attr);
}
}
}

fn visit_mac(&mut self, _mac: &Mac) {}
}

pub fn is_proc_macro_attr(attr: &Attribute) -> bool {
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
.iter().any(|kind| attr.check_name(*kind))
}

crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
let mut result = Vec::new();
attrs.retain(|attr| {
if attr.path != sym::derive {
return true;
}
if !attr.is_meta_item_list() {
cx.struct_span_err(attr.span, "malformed `derive` attribute input")
.span_suggestion(
attr.span,
"missing traits to be derived",
"#[derive(Trait1, Trait2, ...)]".to_owned(),
Applicability::HasPlaceholders,
).emit();
return false;
}

match attr.parse_list(cx.parse_sess,
|parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
Ok(traits) => {
result.extend(traits);
true
}
Err(mut e) => {
e.emit();
false
}
}
});
result
}

crate fn add_derived_markers<T: HasAttrs>(
cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T
) {
let (mut names, mut pretty_name) = (FxHashSet::default(), String::new());
for (i, path) in traits.iter().enumerate() {
if i > 0 {
pretty_name.push_str(", ");
}
pretty_name.push_str(&path.to_string());
names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
}

let span = span.fresh_expansion(cx.current_expansion.id, ExpnInfo::allow_unstable(
ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span,
cx.parse_sess.edition, cx.allow_derive_markers.clone(),
));

item.visit_attrs(|attrs| {
if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) {
let meta = cx.meta_word(span, sym::structural_match);
attrs.push(cx.attribute(span, meta));
}
if names.contains(&sym::Copy) {
let meta = cx.meta_word(span, sym::rustc_copy_clone_marker);
attrs.push(cx.attribute(span, meta));
}
});
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
use errors::{Diagnostic, DiagnosticBuilder};

use std::panic;

use proc_macro::bridge::{server, TokenTree};
use proc_macro::{Delimiter, Level, LineColumn, Spacing};
use crate::ast;
use crate::ext::base::ExtCtxt;
use crate::parse::{self, token, ParseSess};
use crate::parse::lexer::comments;
use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};

use errors::{Diagnostic, DiagnosticBuilder};
use rustc_data_structures::sync::Lrc;
use std::ascii;
use std::ops::Bound;
use syntax::ast;
use syntax::ext::base::ExtCtxt;
use syntax::parse::lexer::comments;
use syntax::parse::{self, token, ParseSess};
use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
use syntax_pos::hygiene::{SyntaxContext, Transparency};
use syntax_pos::symbol::{kw, sym, Symbol};
use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};

use proc_macro::{Delimiter, Level, LineColumn, Spacing};
use proc_macro::bridge::{server, TokenTree};
use std::{ascii, panic};
use std::ops::Bound;

trait FromInternal<T> {
fn from_internal(x: T) -> Self;
@@ -52,7 +50,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
{
fn from_internal(((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec<Self>))
-> Self {
use syntax::parse::token::*;
use crate::parse::token::*;

let joint = is_joint == Joint;
let Token { kind, span } = match tree {
@@ -193,7 +191,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>

impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
fn to_internal(self) -> TokenStream {
use syntax::parse::token::*;
use crate::parse::token::*;

let (ch, joint, span) = match self {
TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span),
15 changes: 10 additions & 5 deletions src/libsyntax/lib.rs
Original file line number Diff line number Diff line change
@@ -18,12 +18,17 @@
#![feature(label_break_value)]
#![feature(mem_take)]
#![feature(nll)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_internals)]
#![feature(proc_macro_span)]
#![feature(rustc_diagnostic_macros)]
#![feature(try_trait)]
#![feature(unicode_internals)]

#![recursion_limit="256"]

extern crate proc_macro;

pub use errors;
use rustc_data_structures::sync::Lock;
use rustc_data_structures::bit_set::GrowableBitSet;
@@ -37,6 +42,7 @@ const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments");
// way towards a non-panic!-prone parser. It should be used for fatal parsing
// errors; eventually we plan to convert all code using panictry to just use
// normal try.
#[macro_export]
macro_rules! panictry {
($e:expr) => ({
use std::result::Result::{Ok, Err};
@@ -147,10 +153,8 @@ pub mod mut_visit;
pub mod parse;
pub mod ptr;
pub mod show_span;
pub mod std_inject;
pub use syntax_pos::edition;
pub use syntax_pos::symbol;
pub mod test;
pub mod tokenstream;
pub mod visit;

@@ -161,14 +165,15 @@ pub mod print {
}

pub mod ext {
mod placeholders;
mod proc_macro_server;

pub use syntax_pos::hygiene;
pub mod allocator;
pub mod base;
pub mod build;
pub mod derive;
pub mod expand;
pub mod placeholders;
pub mod source_util;
pub mod proc_macro;

pub mod tt {
pub mod transcribe;
3 changes: 2 additions & 1 deletion src/libsyntax/parse/lexer/mod.rs
Original file line number Diff line number Diff line change
@@ -794,7 +794,7 @@ mod tests {
use std::path::PathBuf;
use syntax_pos::{BytePos, Span, NO_EXPANSION, edition::Edition};
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use rustc_data_structures::sync::Lock;
use rustc_data_structures::sync::{Lock, Once};

fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()),
@@ -817,6 +817,7 @@ mod tests {
param_attr_spans: Lock::new(Vec::new()),
let_chains_spans: Lock::new(Vec::new()),
async_closure_spans: Lock::new(Vec::new()),
injected_crate_name: Once::new(),
}
}

5 changes: 4 additions & 1 deletion src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
@@ -10,9 +10,10 @@ use crate::parse::token::TokenKind;
use crate::tokenstream::{TokenStream, TokenTree};
use crate::diagnostics::plugin::ErrorMap;
use crate::print::pprust;
use crate::symbol::Symbol;

use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
use rustc_data_structures::sync::{Lrc, Lock};
use rustc_data_structures::sync::{Lrc, Lock, Once};
use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
use syntax_pos::edition::Edition;

@@ -58,6 +59,7 @@ pub struct ParseSess {
pub let_chains_spans: Lock<Vec<Span>>,
// Places where `async || ..` exprs were used and should be feature gated.
pub async_closure_spans: Lock<Vec<Span>>,
pub injected_crate_name: Once<Symbol>,
}

impl ParseSess {
@@ -86,6 +88,7 @@ impl ParseSess {
param_attr_spans: Lock::new(Vec::new()),
let_chains_spans: Lock::new(Vec::new()),
async_closure_spans: Lock::new(Vec::new()),
injected_crate_name: Once::new(),
}
}

3 changes: 1 addition & 2 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@ use crate::parse::{self, ParseSess};
use crate::print::pp::{self, Breaks};
use crate::print::pp::Breaks::{Consistent, Inconsistent};
use crate::ptr::P;
use crate::std_inject;
use crate::symbol::{kw, sym};
use crate::tokenstream::{self, TokenStream, TokenTree};

@@ -114,7 +113,7 @@ pub fn print_crate<'a>(cm: &'a SourceMap,
is_expanded,
};

if is_expanded && std_inject::injected_crate_name().is_some() {
if is_expanded && sess.injected_crate_name.try_get().is_some() {
// We need to print `#![no_std]` (and its feature gate) so that
// compiling pretty-printed source won't inject libstd again.
// However we don't want these attributes in the AST because
8 changes: 4 additions & 4 deletions src/libsyntax_ext/Cargo.toml
Original file line number Diff line number Diff line change
@@ -10,11 +10,11 @@ path = "lib.rs"
doctest = false

[dependencies]
fmt_macros = { path = "../libfmt_macros" }
errors = { path = "../librustc_errors", package = "rustc_errors" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
fmt_macros = { path = "../libfmt_macros" }
log = "0.4"
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_target = { path = "../librustc_target" }
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
log = "0.4"
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
119 changes: 0 additions & 119 deletions src/libsyntax_ext/deriving/custom.rs

This file was deleted.

44 changes: 0 additions & 44 deletions src/libsyntax_ext/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
@@ -1770,50 +1770,6 @@ pub fn cs_fold1<F, B>(use_foldl: bool,
}
}

/// Call the method that is being derived on all the fields, and then
/// process the collected results. i.e.
///
/// ```ignore (only-for-syntax-highlight)
/// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1),
/// self_2.method(__arg_1_2, __arg_2_2)])
/// ```
#[inline]
pub fn cs_same_method<F>(f: F,
mut enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>,
cx: &mut ExtCtxt<'_>,
trait_span: Span,
substructure: &Substructure<'_>)
-> P<Expr>
where F: FnOnce(&mut ExtCtxt<'_>, Span, Vec<P<Expr>>) -> P<Expr>
{
match *substructure.fields {
EnumMatching(.., ref all_fields) |
Struct(_, ref all_fields) => {
// call self_n.method(other_1_n, other_2_n, ...)
let called = all_fields.iter()
.map(|field| {
cx.expr_method_call(field.span,
field.self_.clone(),
substructure.method_ident,
field.other
.iter()
.map(|e| cx.expr_addr_of(field.span, e.clone()))
.collect())
})
.collect();

f(cx, trait_span, called)
}
EnumNonMatchingCollapsed(ref all_self_args, _, tuple) => {
enum_nonmatch_f(cx,
trait_span,
(&all_self_args[..], tuple),
substructure.nonself_args)
}
StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
}
}

/// Returns `true` if the type has no value fields
/// (for an enum, no variant has any fields)
pub fn is_type_without_fields(item: &Annotatable) -> bool {
8 changes: 1 addition & 7 deletions src/libsyntax_ext/deriving/generic/ty.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ pub enum PtrTy<'a> {
/// &'lifetime mut
Borrowed(Option<&'a str>, ast::Mutability),
/// *mut
#[allow(dead_code)]
Raw(ast::Mutability),
}

@@ -107,13 +108,6 @@ pub enum Ty<'a> {
Tuple(Vec<Ty<'a>>),
}

/// A const expression. Supports literals and blocks.
#[derive(Clone, Eq, PartialEq)]
pub enum Const {
Literal,
Block,
}

pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
Borrowed(None, ast::Mutability::Immutable)
}
1 change: 0 additions & 1 deletion src/libsyntax_ext/deriving/mod.rs
Original file line number Diff line number Diff line change
@@ -30,7 +30,6 @@ pub mod decodable;
pub mod hash;
pub mod debug;
pub mod default;
pub mod custom;

#[path="cmp/partial_eq.rs"]
pub mod partial_eq;
24 changes: 10 additions & 14 deletions src/libsyntax_ext/lib.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
//! Syntax extensions in the Rust compiler.
//! This crate contains implementations of built-in macros and other code generating facilities
//! injecting code into the crate before it is lowered to HIR.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]

#![deny(rust_2018_idioms)]
#![deny(unused_lifetimes)]

#![feature(in_band_lifetimes)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_internals)]
#![feature(proc_macro_span)]
#![feature(decl_macro)]
#![feature(mem_take)]
#![feature(nll)]
#![feature(rustc_diagnostic_macros)]
#![feature(unicode_internals)]

#![recursion_limit="256"]

extern crate proc_macro;

mod error_codes;

mod asm;
@@ -26,20 +22,20 @@ mod cfg;
mod compile_error;
mod concat;
mod concat_idents;
mod deriving;
mod env;
mod format;
mod format_foreign;
mod global_allocator;
mod global_asm;
mod log_syntax;
mod proc_macro_server;
mod source_util;
mod test;
mod test_case;
mod trace_macros;

pub mod deriving;
pub mod proc_macro_decls;
pub mod proc_macro_impl;
pub mod proc_macro_harness;
pub mod standard_library_imports;
pub mod test_harness;

use rustc_data_structures::sync::Lrc;
use syntax::ast;
@@ -95,7 +91,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
)* }
}

use syntax::ext::source_util::*;
use source_util::*;
register! {
line: expand_line,
column: expand_column,
@@ -137,7 +133,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
)),
allow_internal_unstable: allow_internal_unstable.clone(),
..SyntaxExtension::default(
SyntaxExtensionKind::LegacyAttr(Box::new(test_case::expand)), edition
SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_test_case)), edition
)
});
register(sym::test, SyntaxExtension {
Original file line number Diff line number Diff line change
@@ -9,21 +9,15 @@ use syntax::ext::base::{ExtCtxt, MacroKind};
use syntax::ext::build::AstBuilder;
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::hygiene::ExpnId;
use syntax::ext::proc_macro::is_proc_macro_attr;
use syntax::mut_visit::MutVisitor;
use syntax::parse::ParseSess;
use syntax::ptr::P;
use syntax::symbol::Symbol;
use syntax::symbol::{kw, sym};
use syntax::visit::{self, Visitor};

use syntax_pos::{Span, DUMMY_SP};

const PROC_MACRO_KINDS: [Symbol; 3] = [
sym::proc_macro_derive,
sym::proc_macro_attribute,
sym::proc_macro
];

struct ProcMacroDerive {
trait_name: ast::Name,
function_name: Ident,
@@ -46,7 +40,7 @@ struct CollectProcMacros<'a> {
is_test_crate: bool,
}

pub fn modify(sess: &ParseSess,
pub fn inject(sess: &ParseSess,
resolver: &mut dyn (::syntax::ext::base::Resolver),
mut krate: ast::Crate,
is_proc_macro_crate: bool,
@@ -90,10 +84,6 @@ pub fn modify(sess: &ParseSess,
krate
}

pub fn is_proc_macro_attr(attr: &ast::Attribute) -> bool {
PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(*kind))
}

impl<'a> CollectProcMacros<'a> {
fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) {
if self.is_proc_macro_crate && self.in_root && vis.node.is_pub() {
68 changes: 0 additions & 68 deletions src/libsyntax_ext/proc_macro_impl.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::ast;
use crate::ext::base::{self, *};
use crate::ext::build::AstBuilder;
use crate::parse::{self, token, DirectoryOwnership};
use crate::print::pprust;
use crate::ptr::P;
use crate::symbol::Symbol;
use crate::tokenstream;
use syntax::{ast, panictry};
use syntax::ext::base::{self, *};
use syntax::ext::build::AstBuilder;
use syntax::parse::{self, token, DirectoryOwnership};
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::symbol::Symbol;
use syntax::tokenstream;

use smallvec::SmallVec;
use syntax_pos::{self, Pos, Span};
@@ -94,7 +94,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstrea
while self.p.token != token::Eof {
match panictry!(self.p.parse_item()) {
Some(item) => ret.push(item),
None => self.p.diagnostic().span_fatal(self.p.token.span,
None => self.p.sess.span_diagnostic.span_fatal(self.p.token.span,
&format!("expected item, found `{}`",
self.p.this_token_to_string()))
.raise()
Original file line number Diff line number Diff line change
@@ -1,37 +1,22 @@
use crate::ast;
use crate::attr;
use crate::edition::Edition;
use crate::ext::hygiene::{ExpnId, MacroKind};
use crate::symbol::{Ident, Symbol, kw, sym};
use crate::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan};
use crate::ptr::P;
use crate::tokenstream::TokenStream;

use std::cell::Cell;
use std::iter;
use syntax::{ast, attr};
use syntax::edition::Edition;
use syntax::ext::hygiene::{ExpnId, MacroKind};
use syntax::ptr::P;
use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan};
use syntax::symbol::{Ident, Symbol, kw, sym};
use syntax::tokenstream::TokenStream;
use syntax_pos::DUMMY_SP;

pub fn injected_crate_name() -> Option<&'static str> {
INJECTED_CRATE_NAME.with(|name| name.get())
}

thread_local! {
// A `Symbol` might make more sense here, but it doesn't work, probably for
// reasons relating to the use of thread-local storage for the Symbol
// interner.
static INJECTED_CRATE_NAME: Cell<Option<&'static str>> = Cell::new(None);
}
use std::iter;

pub fn maybe_inject_crates_ref(
mut krate: ast::Crate,
alt_std_name: Option<&str>,
edition: Edition,
) -> ast::Crate {
pub fn inject(
mut krate: ast::Crate, alt_std_name: Option<&str>, edition: Edition
) -> (ast::Crate, Option<Symbol>) {
let rust_2018 = edition >= Edition::Edition2018;

// the first name in this list is the crate name of the crate with the prelude
let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) {
return krate;
return (krate, None);
} else if attr::contains_name(&krate.attrs, sym::no_std) {
if attr::contains_name(&krate.attrs, sym::compiler_builtins) {
&["core"]
@@ -73,8 +58,6 @@ pub fn maybe_inject_crates_ref(
// the prelude.
let name = names[0];

INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));

let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition,
[sym::prelude_import][..].into(),
@@ -108,5 +91,5 @@ pub fn maybe_inject_crates_ref(
tokens: None,
}));

krate
(krate, Some(Symbol::intern(name)))
}
33 changes: 33 additions & 0 deletions src/libsyntax_ext/test.rs
Original file line number Diff line number Diff line change
@@ -7,11 +7,44 @@ use syntax::ext::base::*;
use syntax::ext::build::AstBuilder;
use syntax::ext::hygiene::SyntaxContext;
use syntax::print::pprust;
use syntax::source_map::respan;
use syntax::symbol::{Symbol, sym};
use syntax_pos::Span;

use std::iter;

// #[test_case] is used by custom test authors to mark tests
// When building for test, it needs to make the item public and gensym the name
// Otherwise, we'll omit the item. This behavior means that any item annotated
// with #[test_case] is never addressable.
//
// We mark item with an inert attribute "rustc_test_marker" which the test generation
// logic will pick up on.
pub fn expand_test_case(
ecx: &mut ExtCtxt<'_>,
attr_sp: Span,
meta_item: &ast::MetaItem,
anno_item: Annotatable
) -> Vec<Annotatable> {
check_builtin_macro_attribute(ecx, meta_item, sym::test_case);

if !ecx.ecfg.should_test { return vec![]; }

let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id));
let mut item = anno_item.expect_item();
item = item.map(|mut item| {
item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
item.ident = item.ident.gensym();
item.attrs.push(
ecx.attribute(sp,
ecx.meta_word(sp, sym::rustc_test_marker))
);
item
});

return vec![Annotatable::Item(item)]
}

pub fn expand_test(
cx: &mut ExtCtxt<'_>,
attr_sp: Span,
44 changes: 0 additions & 44 deletions src/libsyntax_ext/test_case.rs

This file was deleted.

78 changes: 24 additions & 54 deletions src/libsyntax/test.rs → src/libsyntax_ext/test_harness.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,23 @@
// Code that generates a test runner to run all the tests in a crate

#![allow(dead_code)]
#![allow(unused_imports)]

use HasTestSignature::*;

use std::iter;
use std::slice;
use std::mem;
use std::vec;

use log::debug;
use smallvec::{smallvec, SmallVec};
use syntax_pos::{DUMMY_SP, NO_EXPANSION, Span, SourceFile, BytePos};

use crate::attr::{self, HasAttrs};
use crate::source_map::{self, SourceMap, ExpnInfo, ExpnKind, dummy_spanned, respan};
use crate::config;
use crate::entry::{self, EntryPointType};
use crate::ext::base::{ExtCtxt, Resolver};
use crate::ext::build::AstBuilder;
use crate::ext::expand::ExpansionConfig;
use crate::ext::hygiene::{self, ExpnId, SyntaxContext, MacroKind};
use crate::mut_visit::{*, ExpectOne};
use crate::feature_gate::Features;
use crate::util::map_in_place::MapInPlace;
use crate::parse::{token, ParseSess};
use crate::ast::{self, Ident};
use crate::ptr::P;
use crate::symbol::{self, Symbol, kw, sym};
use crate::ThinVec;
use syntax::ast::{self, Ident};
use syntax::attr;
use syntax::entry::{self, EntryPointType};
use syntax::ext::base::{ExtCtxt, Resolver};
use syntax::ext::build::AstBuilder;
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::hygiene::{ExpnId, MacroKind};
use syntax::feature_gate::Features;
use syntax::mut_visit::{*, ExpectOne};
use syntax::parse::ParseSess;
use syntax::ptr::P;
use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned};
use syntax::symbol::{kw, sym, Symbol};
use syntax_pos::{Span, DUMMY_SP};

use std::{iter, mem};

struct Test {
span: Span,
@@ -42,22 +30,21 @@ struct TestCtxt<'a> {
ext_cx: ExtCtxt<'a>,
test_cases: Vec<Test>,
reexport_test_harness_main: Option<Symbol>,
is_libtest: bool,
features: &'a Features,
test_runner: Option<ast::Path>,

// top-level re-export submodule, filled out after folding is finished
toplevel_reexport: Option<Ident>,
}

// Traverse the crate, collecting all the test functions, eliding any
// existing main functions, and synthesizing a main test harness
pub fn modify_for_testing(sess: &ParseSess,
resolver: &mut dyn Resolver,
should_test: bool,
krate: &mut ast::Crate,
span_diagnostic: &errors::Handler,
features: &Features) {
pub fn inject(
sess: &ParseSess,
resolver: &mut dyn Resolver,
should_test: bool,
krate: &mut ast::Crate,
span_diagnostic: &errors::Handler,
features: &Features,
) {
// Check for #[reexport_test_harness_main = "some_name"] which
// creates a `use __test::main as some_name;`. This needs to be
// unconditional, so that the attribute is still marked as used in
@@ -267,11 +254,7 @@ fn generate_test_harness(sess: &ParseSess,
path: Vec::new(),
test_cases: Vec::new(),
reexport_test_harness_main,
// N.B., doesn't consider the value of `--crate-name` passed on the command line.
is_libtest: attr::find_crate_name(&krate.attrs)
.map(|s| s == sym::test).unwrap_or(false),
toplevel_reexport: None,
features,
test_runner
};

@@ -282,19 +265,6 @@ fn generate_test_harness(sess: &ParseSess,
}.visit_crate(krate);
}

enum HasTestSignature {
Yes,
No(BadTestSignature),
}

#[derive(PartialEq)]
enum BadTestSignature {
NotEvenAFunction,
WrongTypeSignature,
NoArgumentsAllowed,
ShouldPanicOnlyWithNoArgs,
}

/// Creates a function item for use as the main function of a test build.
/// This function will call the `test_runner` as specified by the crate attribute
fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
60 changes: 60 additions & 0 deletions src/test/ui/self/arbitrary_self_types_pin_lifetime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// check-pass

use std::pin::Pin;
use std::task::{Context, Poll};

struct Foo;

impl Foo {
fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self }

fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self }

fn pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> Pin<Pin<Pin<&Self>>> { self }

fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self }

fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self }
}

type Alias<T> = Pin<T>;
impl Foo {
fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self }
}

struct Bar<T: Unpin, U: Unpin> {
field1: T,
field2: U,
}

impl<T: Unpin, U: Unpin> Bar<T, U> {
fn fields(self: Pin<&mut Self>) -> (Pin<&mut T>, Pin<&mut U>) {
let this = self.get_mut();
(Pin::new(&mut this.field1), Pin::new(&mut this.field2))
}
}

trait AsyncBufRead {
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>)
-> Poll<std::io::Result<&[u8]>>;
}

struct Baz(Vec<u8>);

impl AsyncBufRead for Baz {
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>)
-> Poll<std::io::Result<&[u8]>>
{
Poll::Ready(Ok(&self.get_mut().0))
}
}

fn main() {
let mut foo = Foo;
{ Pin::new(&foo).pin_ref() };
{ Pin::new(&mut foo).pin_mut() };
{ Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() };
{ Pin::new(&foo).pin_ref_impl_trait() };
let mut bar = Bar { field1: 0u8, field2: 1u8 };
{ Pin::new(&mut bar).fields() };
}
13 changes: 13 additions & 0 deletions src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// compile-fail

use std::pin::Pin;

struct Foo;

impl Foo {
fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR cannot infer an appropriate lifetime
}

fn main() {
{ Pin::new(&Foo).f() };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: cannot infer an appropriate lifetime
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:8:44
|
LL | fn f(self: Pin<&Self>) -> impl Clone { self }
| ---------- ^^^^ ...but this borrow...
| |
| this return type evaluates to the `'static` lifetime...
|
note: ...can't outlive the anonymous lifetime #1 defined on the method body at 8:5
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:8:5
|
LL | fn f(self: Pin<&Self>) -> impl Clone { self }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 8:5
|
LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ^^^^^^^^^^^^^^^

error: aborting due to previous error

18 changes: 18 additions & 0 deletions src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// compile-fail

use std::pin::Pin;

struct Foo;

impl Foo {
fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } //~ ERROR E0623

fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } //~ ERROR E0623
}

type Alias<T> = Pin<T>;
impl Foo {
fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623
}

fn main() {}
26 changes: 26 additions & 0 deletions src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error[E0623]: lifetime mismatch
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:46
|
LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
| ---- ---- ^ ...but data from `f` is returned here
| |
| this parameter and the return type are declared with different lifetimes...

error[E0623]: lifetime mismatch
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:10:76
|
LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
| ---- ----------------- ^ ...but data from `f` is returned here
| |
| this parameter and the return type are declared with different lifetimes...

error[E0623]: lifetime mismatch
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58
|
LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
| ------ --- ^^^ ...but data from `arg` is returned here
| |
| this parameter and the return type are declared with different lifetimes...

error: aborting due to 3 previous errors

44 changes: 44 additions & 0 deletions src/test/ui/self/elision/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Test cases intended to to document behavior and try to exhaustively
explore the combinations.

## Confidence

These tests are not yet considered 100% normative, in that some
aspects of the current behavior are not desirable. This is expressed
in the "confidence" field in the following table. Values:

| Confidence | Interpretation |
| --- | --- |
| 100% | this will remain recommended behavior |
| 75% | unclear whether we will continue to accept this |
| 50% | this will likely be deprecated but remain valid |
| 25% | this could change in the future |
| 0% | this is definitely bogus and will likely change in the future in *some* way |

## Tests

| Test file | `Self` type | Pattern | Current elision behavior | Confidence |
| --- | --- | --- | --- | --- |
| `self.rs` | `Struct` | `Self` | ignore `self` parameter | 100% |
| `struct.rs` | `Struct` | `Struct` | ignore `self` parameter | 100% |
| `alias.rs` | `Struct` | `Alias` | ignore `self` parameter | 100% |
| `ref-self.rs` | `Struct` | `&Self` | take lifetime from `&Self` | 100% |
| `ref-mut-self.rs` | `Struct` | `&mut Self` | take lifetime from `&mut Self` | 100% |
| `ref-struct.rs` | `Struct` | `&Struct` | take lifetime from `&Self` | 50% |
| `ref-mut-struct.rs` | `Struct` | `&mut Struct` | take lifetime from `&mut Self` | 50% |
| `ref-alias.rs` | `Struct` | `&Alias` | ignore `Alias` | 0% |
| `ref-mut-alias.rs` | `Struct` | `&mut Alias` | ignore `Alias` | 0% |
| `lt-self.rs` | `Struct<'a>` | `Self` | ignore `Self` (and hence `'a`) | 25% |
| `lt-struct.rs` | `Struct<'a>` | `Self` | ignore `Self` (and hence `'a`) | 0% |
| `lt-alias.rs` | `Alias<'a>` | `Self` | ignore `Self` (and hence `'a`) | 0% |
| `lt-ref-self.rs` | `Struct<'a>` | `&Self` | take lifetime from `&Self` | 75% |

In each case, we test the following patterns:

- `self: XXX`
- `self: Box<XXX>`
- `self: Pin<XXX>`
- `self: Box<Box<XXX>>`
- `self: Box<Pin<XXX>>`

In the non-reference cases, `Pin` causes errors so we substitute `Rc`.
36 changes: 36 additions & 0 deletions src/test/ui/self/elision/alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::rc::Rc;

struct Struct { }

type Alias = Struct;

impl Struct {
// Test using an alias for `Struct`:

fn alias(self: Alias, f: &u32) -> &u32 {
f
}

fn box_Alias(self: Box<Alias>, f: &u32) -> &u32 {
f
}

fn rc_Alias(self: Rc<Alias>, f: &u32) -> &u32 {
f
}

fn box_box_Alias(self: Box<Box<Alias>>, f: &u32) -> &u32 {
f
}

fn box_rc_Alias(self: Box<Rc<Alias>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
40 changes: 40 additions & 0 deletions src/test/ui/self/elision/assoc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::rc::Rc;

trait Trait {
type AssocType;
}

struct Struct { }

impl Trait for Struct {
type AssocType = Self;
}

impl Struct {
fn assoc(self: <Struct as Trait>::AssocType, f: &u32) -> &u32 {
f
}

fn box_AssocType(self: Box<<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
f
}

fn rc_AssocType(self: Rc<<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
f
}

fn box_box_AssocType(self: Box<Box<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
f
}

fn box_rc_AssocType(self: Box<Rc<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
38 changes: 38 additions & 0 deletions src/test/ui/self/elision/lt-alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::rc::Rc;

struct Struct<'a> { x: &'a u32 }

type Alias<'a> = Struct<'a>;

impl<'a> Alias<'a> {
fn take_self(self, f: &u32) -> &u32 {
f
}

fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 {
f
}

fn take_Box_Alias(self: Box<Alias<'a>>, f: &u32) -> &u32 {
f
}

fn take_Box_Box_Alias(self: Box<Box<Alias<'a>>>, f: &u32) -> &u32 {
f
}

fn take_Rc_Alias(self: Rc<Alias<'a>>, f: &u32) -> &u32 {
f
}

fn take_Box_Rc_Alias(self: Box<Rc<Alias<'a>>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
44 changes: 44 additions & 0 deletions src/test/ui/self/elision/lt-assoc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::rc::Rc;

trait Trait {
type AssocType;
}

struct Struct<'a> { x: &'a u32 }

impl<'a> Trait for Struct<'a> {
type AssocType = Self;
}

impl<'a> Struct<'a> {
fn take_self(self, f: &u32) -> &u32 {
f
}

fn take_AssocType(self: <Struct<'a> as Trait>::AssocType, f: &u32) -> &u32 {
f
}

fn take_Box_AssocType(self: Box<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 {
f
}

fn take_Box_Box_AssocType(self: Box<Box<<Struct<'a> as Trait>::AssocType>>, f: &u32) -> &u32 {
f
}

fn take_Rc_AssocType(self: Rc<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 {
f
}

fn take_Box_Rc_AssocType(self: Box<Rc<<Struct<'a> as Trait>::AssocType>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
38 changes: 38 additions & 0 deletions src/test/ui/self/elision/lt-ref-self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::pin::Pin;

struct Struct<'a> { data: &'a u32 }

impl<'a> Struct<'a> {
// Test using `&self` sugar:

fn ref_self(&self, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

// Test using `&Self` explicitly:

fn ref_Self(self: &Self, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}
}

fn main() { }
62 changes: 62 additions & 0 deletions src/test/ui/self/elision/lt-ref-self.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
error[E0623]: lifetime mismatch
--> $DIR/lt-ref-self.rs:12:9
|
LL | fn ref_self(&self, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/lt-ref-self.rs:18:9
|
LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/lt-ref-self.rs:22:9
|
LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/lt-ref-self.rs:26:9
|
LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/lt-ref-self.rs:30:9
|
LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/lt-ref-self.rs:34:9
|
LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error: aborting due to 6 previous errors

49 changes: 49 additions & 0 deletions src/test/ui/self/elision/lt-self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::pin::Pin;
use std::rc::Rc;

struct Struct<'a> {
x: &'a u32
}

impl<'a> Struct<'a> {
fn take_self(self, f: &u32) -> &u32 {
f
}

fn take_Self(self: Self, f: &u32) -> &u32 {
f
}

fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 {
f
}

fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 {
f
}

fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 {
f
}

fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 {
f
}

// N/A
//fn take_Pin_Self(self: Pin<Self>, f: &u32) -> &u32 {
// f
//}

// N/A
//fn take_Box_Pin_Self(self: Box<Pin<Self>>, f: &u32) -> &u32 {
// f
//}
}

fn main() { }
36 changes: 36 additions & 0 deletions src/test/ui/self/elision/lt-struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::rc::Rc;

struct Struct<'a> { x: &'a u32 }

impl<'a> Struct<'a> {
fn take_self(self, f: &u32) -> &u32 {
f
}

fn take_Struct(self: Struct<'a>, f: &u32) -> &u32 {
f
}

fn take_Box_Struct(self: Box<Struct<'a>>, f: &u32) -> &u32 {
f
}

fn take_Box_Box_Struct(self: Box<Box<Struct<'a>>>, f: &u32) -> &u32 {
f
}

fn take_Rc_Struct(self: Rc<Struct<'a>>, f: &u32) -> &u32 {
f
}

fn take_Box_Rc_Struct(self: Box<Rc<Struct<'a>>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
43 changes: 43 additions & 0 deletions src/test/ui/self/elision/multiple-ref-self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::marker::PhantomData;
use std::ops::Deref;
use std::pin::Pin;

struct Struct { }

struct Wrap<T, P>(T, PhantomData<P>);

impl<T, P> Deref for Wrap<T, P> {
type Target = T;
fn deref(&self) -> &T { &self.0 }
}

impl Struct {
// Test using multiple `&Self`:

fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
f
}

fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
f
}

fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
f
}

fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
f
}

fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
39 changes: 39 additions & 0 deletions src/test/ui/self/elision/ref-alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::pin::Pin;

struct Struct { }

type Alias = Struct;

impl Struct {
// Test using an alias for `Struct`:
//
// FIXME. We currently fail to recognize this as the self type, which
// feels like a bug.

fn ref_Alias(self: &Alias, f: &u32) -> &u32 {
f
}

fn box_ref_Alias(self: Box<&Alias>, f: &u32) -> &u32 {
f
}

fn pin_ref_Alias(self: Pin<&Alias>, f: &u32) -> &u32 {
f
}

fn box_box_ref_Alias(self: Box<Box<&Alias>>, f: &u32) -> &u32 {
f
}

fn box_pin_ref_Alias(self: Box<Pin<&Alias>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
40 changes: 40 additions & 0 deletions src/test/ui/self/elision/ref-assoc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::pin::Pin;

trait Trait {
type AssocType;
}

struct Struct { }

impl Trait for Struct {
type AssocType = Self;
}

impl Struct {
fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 {
f
}

fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
f
}

fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
f
}

fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
f
}

fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
36 changes: 36 additions & 0 deletions src/test/ui/self/elision/ref-mut-alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::pin::Pin;

struct Struct { }

type Alias = Struct;

impl Struct {
// Test using an alias for `Struct`:

fn ref_Alias(self: &mut Alias, f: &u32) -> &u32 {
f
}

fn box_ref_Alias(self: Box<&mut Alias>, f: &u32) -> &u32 {
f
}

fn pin_ref_Alias(self: Pin<&mut Alias>, f: &u32) -> &u32 {
f
}

fn box_box_ref_Alias(self: Box<Box<&mut Alias>>, f: &u32) -> &u32 {
f
}

fn box_pin_ref_Alias(self: Box<Pin<&mut Alias>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
38 changes: 38 additions & 0 deletions src/test/ui/self/elision/ref-mut-self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::pin::Pin;

struct Struct { }

impl Struct {
// Test using `&mut self` sugar:

fn ref_self(&mut self, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

// Test using `&mut Self` explicitly:

fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}
}

fn main() { }
62 changes: 62 additions & 0 deletions src/test/ui/self/elision/ref-mut-self.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
error[E0623]: lifetime mismatch
--> $DIR/ref-mut-self.rs:12:9
|
LL | fn ref_self(&mut self, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-mut-self.rs:18:9
|
LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-mut-self.rs:22:9
|
LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-mut-self.rs:26:9
|
LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-mut-self.rs:30:9
|
LL | fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-mut-self.rs:34:9
|
LL | fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error: aborting due to 6 previous errors

32 changes: 32 additions & 0 deletions src/test/ui/self/elision/ref-mut-struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::pin::Pin;

struct Struct { }

impl Struct {
// Test using `&mut Struct` explicitly:

fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}
}

fn main() { }
52 changes: 52 additions & 0 deletions src/test/ui/self/elision/ref-mut-struct.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
error[E0623]: lifetime mismatch
--> $DIR/ref-mut-struct.rs:12:9
|
LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-mut-struct.rs:16:9
|
LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-mut-struct.rs:20:9
|
LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-mut-struct.rs:24:9
|
LL | fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-mut-struct.rs:28:9
|
LL | fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error: aborting due to 5 previous errors

51 changes: 51 additions & 0 deletions src/test/ui/self/elision/ref-self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::marker::PhantomData;
use std::ops::Deref;
use std::pin::Pin;

struct Struct { }

struct Wrap<T, P>(T, PhantomData<P>);

impl<T, P> Deref for Wrap<T, P> {
type Target = T;
fn deref(&self) -> &T { &self.0 }
}

impl Struct {
// Test using `&self` sugar:

fn ref_self(&self, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

// Test using `&Self` explicitly:

fn ref_Self(self: &Self, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
f //~ ERROR lifetime mismatch
}
}

fn main() { }
72 changes: 72 additions & 0 deletions src/test/ui/self/elision/ref-self.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
error[E0623]: lifetime mismatch
--> $DIR/ref-self.rs:21:9
|
LL | fn ref_self(&self, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-self.rs:27:9
|
LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-self.rs:31:9
|
LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-self.rs:35:9
|
LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-self.rs:39:9
|
LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-self.rs:43:9
|
LL | fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-self.rs:47:9
|
LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
| --- ---
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error: aborting due to 7 previous errors

32 changes: 32 additions & 0 deletions src/test/ui/self/elision/ref-struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::pin::Pin;

struct Struct { }

impl Struct {
// Test using `&Struct` explicitly:

fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}

fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
f //~ ERROR lifetime mismatch
}
}

fn main() { }
52 changes: 52 additions & 0 deletions src/test/ui/self/elision/ref-struct.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
error[E0623]: lifetime mismatch
--> $DIR/ref-struct.rs:12:9
|
LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-struct.rs:16:9
|
LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-struct.rs:20:9
|
LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-struct.rs:24:9
|
LL | fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error[E0623]: lifetime mismatch
--> $DIR/ref-struct.rs:28:9
|
LL | fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| ---- ----
| |
| this parameter and the return type are declared with different lifetimes...
LL | f
| ^ ...but data from `f` is returned here

error: aborting due to 5 previous errors

36 changes: 36 additions & 0 deletions src/test/ui/self/elision/self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::rc::Rc;

struct Struct { }

impl Struct {
fn take_self(self, f: &u32) -> &u32 {
f
}

fn take_Self(self: Self, f: &u32) -> &u32 {
f
}

fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 {
f
}

fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 {
f
}

fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 {
f
}

fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
32 changes: 32 additions & 0 deletions src/test/ui/self/elision/struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// check-pass

#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]

use std::rc::Rc;

struct Struct { }

impl Struct {
fn ref_Struct(self: Struct, f: &u32) -> &u32 {
f
}

fn box_Struct(self: Box<Struct>, f: &u32) -> &u32 {
f
}

fn rc_Struct(self: Rc<Struct>, f: &u32) -> &u32 {
f
}

fn box_box_Struct(self: Box<Box<Struct>>, f: &u32) -> &u32 {
f
}

fn box_rc_Struct(self: Box<Rc<Struct>>, f: &u32) -> &u32 {
f
}
}

fn main() { }
15 changes: 15 additions & 0 deletions src/test/ui/self/self_lifetime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// check-pass

// https://github.com/rust-lang/rust/pull/60944#issuecomment-495346120

struct Foo<'a>(&'a ());
impl<'a> Foo<'a> {
fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
}

type Alias = Foo<'static>;
impl Alias {
fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
}

fn main() {}
40 changes: 40 additions & 0 deletions src/test/ui/suggestions/auxiliary/issue-61963-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]

extern crate proc_macro;

use proc_macro::{Group, TokenStream, TokenTree};

// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2.

#[proc_macro_derive(DomObject)]
pub fn expand_token_stream(input: TokenStream) -> TokenStream {
// Construct a dummy span - `#0 bytes(0..0)` - which is present in the input because
// of the specially crafted generated tokens in the `attribute-crate` proc-macro.
let dummy_span = input.clone().into_iter().nth(0).unwrap().span();

// Define what the macro would output if constructed properly from the source using syn/quote.
let output: TokenStream = "impl Bar for ((), Qux<Qux<Baz> >) { }
impl Bar for ((), Box<Bar>) { }".parse().unwrap();

let mut tokens: Vec<_> = output.into_iter().collect();
// Adjust token spans to match the original crate (which would use `quote`). Some of the
// generated tokens point to the dummy span.
for token in tokens.iter_mut() {
if let TokenTree::Group(group) = token {
let mut tokens: Vec<_> = group.stream().into_iter().collect();
for token in tokens.iter_mut().skip(2) {
token.set_span(dummy_span);
}

let mut stream = TokenStream::new();
stream.extend(tokens);
*group = Group::new(group.delimiter(), stream);
}
}

let mut output = TokenStream::new();
output.extend(tokens);
output
}
41 changes: 41 additions & 0 deletions src/test/ui/suggestions/auxiliary/issue-61963.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]

extern crate proc_macro;

use proc_macro::{Group, Spacing, Punct, TokenTree, TokenStream};

// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2.

#[proc_macro_attribute]
pub fn dom_struct(_: TokenStream, input: TokenStream) -> TokenStream {
// Construct the expected output tokens - the input but with a `#[derive(DomObject)]` applied.
let attributes: TokenStream =
"#[derive(DomObject)]".to_string().parse().unwrap();
let output: TokenStream = attributes.into_iter()
.chain(input.into_iter()).collect();

let mut tokens: Vec<_> = output.into_iter().collect();
// Adjust the spacing of `>` tokens to match what `quote` would produce.
for token in tokens.iter_mut() {
if let TokenTree::Group(group) = token {
let mut tokens: Vec<_> = group.stream().into_iter().collect();
for token in tokens.iter_mut() {
if let TokenTree::Punct(p) = token {
if p.as_char() == '>' {
*p = Punct::new('>', Spacing::Alone);
}
}
}

let mut stream = TokenStream::new();
stream.extend(tokens);
*group = Group::new(group.delimiter(), stream);
}
}

let mut output = TokenStream::new();
output.extend(tokens);
output
}
24 changes: 24 additions & 0 deletions src/test/ui/suggestions/issue-61963.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// aux-build:issue-61963.rs
// aux-build:issue-61963-1.rs
#![deny(bare_trait_objects)]

#[macro_use]
extern crate issue_61963;
#[macro_use]
extern crate issue_61963_1;

// This test checks that the bare trait object lint does not trigger on macro attributes that
// generate code which would trigger the lint.

pub struct Baz;
pub trait Bar { }
pub struct Qux<T>(T);

#[dom_struct]
pub struct Foo {
qux: Qux<Qux<Baz>>,
bar: Box<Bar>,
//~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
}

fn main() {}
14 changes: 14 additions & 0 deletions src/test/ui/suggestions/issue-61963.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: trait objects without an explicit `dyn` are deprecated
--> $DIR/issue-61963.rs:20:14
|
LL | bar: Box<Bar>,
| ^^^ help: use `dyn`: `dyn Bar`
|
note: lint level defined here
--> $DIR/issue-61963.rs:3:9
|
LL | #![deny(bare_trait_objects)]
| ^^^^^^^^^^^^^^^^^^

error: aborting due to previous error