Skip to content
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

Rollup of 5 pull requests #65053

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c845f3d
track the kind of async generator we are creating
nikomatsakis Sep 25, 2019
44e801a
thread down the body so we can check if this is an async fn body
nikomatsakis Sep 25, 2019
c8e5851
improved debug output
nikomatsakis Oct 2, 2019
f7ed53c
extract expected return type from `-> impl Future` obligation
nikomatsakis Oct 2, 2019
094f3a8
WIP tidy hir/lowering/expr.rs
nikomatsakis Oct 2, 2019
81cd596
WIP rebase for `shallow_resolve` call
nikomatsakis Oct 2, 2019
dce20bf
WIP fix tests
nikomatsakis Oct 2, 2019
3ae4abb
correct coercion comments
nikomatsakis Oct 2, 2019
a999132
improve comments on `GeneratorKind` and `AsyncGeneratorKind`
nikomatsakis Oct 2, 2019
5d64b3d
document `ret_coercion` and `ret_coercion_span`
nikomatsakis Oct 2, 2019
5fea1d2
document `shallow_resolve`
nikomatsakis Oct 2, 2019
3f277e1
s/`async` fn/`async fn`/
nikomatsakis Oct 2, 2019
a5cfc40
Avoid ICE on ReFree region from malformed code
estebank Oct 1, 2019
a96bce7
avoid using `skip_binder` and instead look for bound vars properly
nikomatsakis Oct 2, 2019
08a60ac
Calculate liveness for the same locals with and without -Zpolonius
matthewjasper Sep 21, 2019
2180c24
Make lifetimes in constants live at the point of use
matthewjasper Sep 24, 2019
4a49351
add unsize slice-str coercion
nikomatsakis Oct 2, 2019
19c07cc
fix example (le sigh)
nikomatsakis Oct 2, 2019
de81565
review comments
estebank Oct 2, 2019
a8b2fe0
[RFC 2091] Add #[track_caller] attribute.
ayosec Jul 20, 2019
e9deff0
track_caller run-pass test, lint cleanup, PR review.
anp Oct 3, 2019
1e78d99
track_caller feature gate starts in 1.40.0.
anp Oct 3, 2019
da86007
Mark #![feature(track_caller)] as incomplete.
anp Oct 3, 2019
8ac9104
track_caller error numbers and text.
anp Oct 3, 2019
9e301d1
track_caller tests account for incomplete feature warning.
anp Oct 3, 2019
a807032
./x.py test --bless --compare-mode=nll
nikomatsakis Oct 3, 2019
d1310dc
proc_macro: Add `Span::mixed_site` exposing `macro_rules` hygiene
petrochenkov Sep 22, 2019
49c8463
Rollup merge of #64690 - petrochenkov:mixed, r=dtolnay
Centril Oct 3, 2019
1172cd4
Rollup merge of #64749 - matthewjasper:liveness-opt, r=nikomatsakis
Centril Oct 3, 2019
f22cd77
Rollup merge of #64938 - estebank:ice-ice-baby, r=matthewjasper
Centril Oct 3, 2019
83adae8
Rollup merge of #64999 - nikomatsakis:issue-60424-async-return-infere…
Centril Oct 3, 2019
18ce550
Rollup merge of #65037 - anp:track-caller, r=oli-obk
Centril Oct 3, 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
5 changes: 5 additions & 0 deletions src/doc/unstable-book/src/language-features/track-caller.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# `track_caller`

The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).

------------------------
1 change: 1 addition & 0 deletions src/libproc_macro/bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ macro_rules! with_api {
fn debug($self: $S::Span) -> String;
fn def_site() -> $S::Span;
fn call_site() -> $S::Span;
fn mixed_site() -> $S::Span;
fn source_file($self: $S::Span) -> $S::SourceFile;
fn parent($self: $S::Span) -> Option<$S::Span>;
fn source($self: $S::Span) -> $S::Span;
Expand Down
9 changes: 9 additions & 0 deletions src/libproc_macro/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,15 @@ impl Span {
Span(bridge::client::Span::call_site())
}

/// A span that represents `macro_rules` hygiene, and sometimes resolves at the macro
/// definition site (local variables, labels, `$crate`) and sometimes at the macro
/// call site (everything else).
/// The span location is taken from the call-site.
#[unstable(feature = "proc_macro_mixed_site", issue = "65049")]
pub fn mixed_site() -> Span {
Span(bridge::client::Span::mixed_site())
}

/// The original source file into which this span points.
#[unstable(feature = "proc_macro_span", issue = "54725")]
pub fn source_file(&self) -> SourceFile {
Expand Down
10 changes: 10 additions & 0 deletions src/librustc/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2234,6 +2234,15 @@ These attributes are meant to only be used by the standard library and are
rejected in your own crates.
"##,

E0736: r##"
#[track_caller] and #[naked] cannot be applied to the same function.

This is primarily due to ABI incompatibilities between the two attributes.
See [RFC 2091] for details on this and other limitations.

[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
"##,

;
// E0006, // merged with E0005
// E0101, // replaced with E0282
Expand Down Expand Up @@ -2296,4 +2305,5 @@ rejected in your own crates.
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
E0727, // `async` generators are not yet supported
E0728, // `await` must be in an `async` function or block
E0735, // invalid track_caller application/syntax
}
30 changes: 29 additions & 1 deletion src/librustc/hir/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::ty::TyCtxt;
use crate::ty::query::Providers;

use std::fmt::{self, Display};
use syntax::symbol::sym;
use syntax::{attr, symbol::sym};
use syntax_pos::Span;

#[derive(Copy, Clone, PartialEq)]
Expand Down Expand Up @@ -103,6 +103,8 @@ impl CheckAttrVisitor<'tcx> {
self.check_marker(attr, item, target)
} else if attr.check_name(sym::target_feature) {
self.check_target_feature(attr, item, target)
} else if attr.check_name(sym::track_caller) {
self.check_track_caller(attr, &item, target)
} else {
true
};
Expand Down Expand Up @@ -135,6 +137,32 @@ impl CheckAttrVisitor<'tcx> {
}
}

/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool {
if target != Target::Fn {
struct_span_err!(
self.tcx.sess,
attr.span,
E0735,
"attribute should be applied to function"
)
.span_label(item.span, "not a function")
.emit();
false
} else if attr::contains_name(&item.attrs, sym::naked) {
struct_span_err!(
self.tcx.sess,
attr.span,
E0736,
"cannot use `#[track_caller]` with `#[naked]`",
)
.emit();
false
} else {
true
}
}

/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
fn check_non_exhaustive(
&self,
Expand Down
30 changes: 19 additions & 11 deletions src/librustc/hir/lowering/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,14 @@ impl LoweringContext<'_> {
hir::MatchSource::Normal,
),
ExprKind::Async(capture_clause, closure_node_id, ref block) => {
self.make_async_expr(capture_clause, closure_node_id, None, block.span, |this| {
this.with_new_scopes(|this| this.lower_block_expr(block))
})
self.make_async_expr(
capture_clause,
closure_node_id,
None,
block.span,
hir::AsyncGeneratorKind::Block,
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
)
}
ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr),
ExprKind::Closure(
Expand Down Expand Up @@ -457,6 +462,7 @@ impl LoweringContext<'_> {
closure_node_id: NodeId,
ret_ty: Option<AstP<Ty>>,
span: Span,
async_gen_kind: hir::AsyncGeneratorKind,
body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
) -> hir::ExprKind {
let capture_clause = self.lower_capture_clause(capture_clause);
Expand All @@ -470,7 +476,7 @@ impl LoweringContext<'_> {
};
let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None);
let body_id = self.lower_fn_body(&ast_decl, |this| {
this.generator_kind = Some(hir::GeneratorKind::Async);
this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
body(this)
});

Expand Down Expand Up @@ -522,7 +528,7 @@ impl LoweringContext<'_> {
/// ```
fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind {
match self.generator_kind {
Some(hir::GeneratorKind::Async) => {},
Some(hir::GeneratorKind::Async(_)) => {},
Some(hir::GeneratorKind::Gen) |
None => {
let mut err = struct_span_err!(
Expand Down Expand Up @@ -727,7 +733,7 @@ impl LoweringContext<'_> {
Movability::Static => hir::GeneratorMovability::Static,
})
},
Some(hir::GeneratorKind::Async) => {
Some(hir::GeneratorKind::Async(_)) => {
bug!("non-`async` closure body turned `async` during lowering");
},
None => {
Expand Down Expand Up @@ -786,10 +792,12 @@ impl LoweringContext<'_> {
None
};
let async_body = this.make_async_expr(
capture_clause, closure_id, async_ret_ty, body.span,
|this| {
this.with_new_scopes(|this| this.lower_expr(body))
}
capture_clause,
closure_id,
async_ret_ty,
body.span,
hir::AsyncGeneratorKind::Closure,
|this| this.with_new_scopes(|this| this.lower_expr(body)),
);
this.expr(fn_decl_span, async_body, ThinVec::new())
});
Expand Down Expand Up @@ -1005,7 +1013,7 @@ impl LoweringContext<'_> {
fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind {
match self.generator_kind {
Some(hir::GeneratorKind::Gen) => {},
Some(hir::GeneratorKind::Async) => {
Some(hir::GeneratorKind::Async(_)) => {
span_err!(
self.sess,
span,
Expand Down
6 changes: 5 additions & 1 deletion src/librustc/hir/lowering/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,11 @@ impl LoweringContext<'_> {
}

let async_expr = this.make_async_expr(
CaptureBy::Value, closure_id, None, body.span,
CaptureBy::Value,
closure_id,
None,
body.span,
hir::AsyncGeneratorKind::Fn,
|this| {
// Create a block from the user's function body:
let user_body = this.lower_block_expr(body);
Expand Down
43 changes: 37 additions & 6 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1362,21 +1362,49 @@ impl Body {
}

/// The type of source expression that caused this generator to be created.
// Not `IsAsync` because we want to eventually add support for `AsyncGen`
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum GeneratorKind {
/// An `async` block or function.
Async,
/// An explicit `async` block or the body of an async function.
Async(AsyncGeneratorKind),

/// A generator literal created via a `yield` inside a closure.
Gen,
}

impl fmt::Display for GeneratorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GeneratorKind::Async(k) => fmt::Display::fmt(k, f),
GeneratorKind::Gen => f.write_str("generator"),
}
}
}

/// In the case of a generator created as part of an async construct,
/// which kind of async construct caused it to be created?
///
/// This helps error messages but is also used to drive coercions in
/// type-checking (see #60424).
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum AsyncGeneratorKind {
/// An explicit `async` block written by the user.
Block,

/// An explicit `async` block written by the user.
Closure,

/// The `async` block generated as the body of an async function.
Fn,
}

impl fmt::Display for AsyncGeneratorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
GeneratorKind::Async => "`async` object",
GeneratorKind::Gen => "generator",
AsyncGeneratorKind::Block => "`async` block",
AsyncGeneratorKind::Closure => "`async` closure body",
AsyncGeneratorKind::Fn => "`async fn` body",
})
}
}
Expand Down Expand Up @@ -1758,6 +1786,7 @@ pub struct Destination {
pub enum GeneratorMovability {
/// May contain self-references, `!Unpin`.
Static,

/// Must not contain self-references, `Unpin`.
Movable,
}
Expand Down Expand Up @@ -2687,7 +2716,9 @@ bitflags! {
const USED = 1 << 9;
/// #[ffi_returns_twice], indicates that an extern function can return
/// multiple times
const FFI_RETURNS_TWICE = 1 << 10;
const FFI_RETURNS_TWICE = 1 << 10;
/// #[track_caller]: allow access to the caller location
const TRACK_CALLER = 1 << 11;
}
}

Expand Down
11 changes: 11 additions & 0 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}

/// Resolve any type variables found in `value` -- but only one
/// level. So, if the variable `?X` is bound to some type
/// `Foo<?Y>`, then this would return `Foo<?Y>` (but `?Y` may
/// itself be bound to a type).
///
/// Useful when you only need to inspect the outermost level of
/// the type and don't care about nested types (or perhaps you
/// will be resolving them as well, e.g. in a loop).
pub fn shallow_resolve<T>(&self, value: T) -> T
where
T: TypeFoldable<'tcx>,
Expand Down Expand Up @@ -1579,6 +1587,9 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
ShallowResolver { infcx }
}

/// If `typ` is a type variable of some kind, resolve it one level
/// (but do not resolve types found in the result). If `typ` is
/// not a type variable, just return it unmodified.
pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> {
match typ.kind {
ty::Infer(ty::TyVar(v)) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ impl LocalUseMap {
appearances: IndexVec::new(),
};

if live_locals.is_empty() {
return local_use_map;
}

let mut locals_with_use_data: IndexVec<Local, bool> =
IndexVec::from_elem_n(false, body.local_decls.len());
live_locals.iter().for_each(|&local| locals_with_use_data[local] = true);
Expand Down
52 changes: 30 additions & 22 deletions src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,39 @@ pub(super) fn generate<'tcx>(
) {
debug!("liveness::generate");

let live_locals: Vec<Local> = if AllFacts::enabled(typeck.tcx()) {
// If "dump facts from NLL analysis" was requested perform
// the liveness analysis for all `Local`s. This case opens
// the possibility of the variables being analyzed in `trace`
// to be *any* `Local`, not just the "live" ones, so we can't
// make any assumptions past this point as to the characteristics
// of the `live_locals`.
// FIXME: Review "live" terminology past this point, we should
// not be naming the `Local`s as live.
body.local_decls.indices().collect()
let free_regions = regions_that_outlive_free_regions(
typeck.infcx.num_region_vars(),
&typeck.borrowck_context.universal_regions,
&typeck.borrowck_context.constraints.outlives_constraints,
);
let live_locals = compute_live_locals(typeck.tcx(), &free_regions, body);
let facts_enabled = AllFacts::enabled(typeck.tcx());


let polonius_drop_used = if facts_enabled {
let mut drop_used = Vec::new();
polonius::populate_access_facts(
typeck,
body,
location_table,
move_data,
&mut drop_used,
);
Some(drop_used)
} else {
let free_regions = {
regions_that_outlive_free_regions(
typeck.infcx.num_region_vars(),
&typeck.borrowck_context.universal_regions,
&typeck.borrowck_context.constraints.outlives_constraints,
)
};
compute_live_locals(typeck.tcx(), &free_regions, body)
None
};

if !live_locals.is_empty() {
trace::trace(typeck, body, elements, flow_inits, move_data, live_locals);

polonius::populate_access_facts(typeck, body, location_table, move_data);
if !live_locals.is_empty() || facts_enabled {
trace::trace(
typeck,
body,
elements,
flow_inits,
move_data,
live_locals,
polonius_drop_used,
);
}
}

Expand Down
Loading