Skip to content

Commit

Permalink
Auto merge of rust-lang#63043 - Centril:rollup-f4baee4, r=Centril
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - rust-lang#62423 (Fix cycle error with existential types)
 - rust-lang#62979 (Cleanup save-analysis JsonDumper)
 - rust-lang#62982 (Don't access a static just for its size and alignment)
 - rust-lang#63013 (add `repr(transparent)` to `IoSliceMut` where missing)
 - rust-lang#63014 (Stop bare trait lint applying to macro call sites)
 - rust-lang#63036 (Add lib section to rustc_lexer's Cargo.toml)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Jul 27, 2019
2 parents 0e9b465 + 51769b3 commit a5e7bb3
Show file tree
Hide file tree
Showing 26 changed files with 388 additions and 219 deletions.
22 changes: 15 additions & 7 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5753,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(
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_lexer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ edition = "2018"
# Note that this crate purposefully does not depend on other rustc crates
[dependencies]
unicode-xid = { version = "0.1.0", optional = true }

# Note: do not remove this blank `[lib]` section.
# This will be used when publishing this crate as `rustc-ap-rustc_lexer`.
[lib]
doctest = false
name = "rustc_lexer"
38 changes: 33 additions & 5 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1281,15 +1281,43 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let opaque_defn_ty = tcx.type_of(opaque_def_id);
let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs);
let opaque_defn_ty = renumber::renumber_regions(infcx, &opaque_defn_ty);
let concrete_is_opaque = infcx
.resolve_vars_if_possible(&opaque_decl.concrete_ty).is_impl_trait();

debug!(
"eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
"eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?} \
concrete_is_opaque={}",
opaque_decl.concrete_ty,
infcx.resolve_vars_if_possible(&opaque_decl.concrete_ty),
opaque_defn_ty
opaque_defn_ty,
concrete_is_opaque
);
obligations.add(infcx
.at(&ObligationCause::dummy(), param_env)
.eq(opaque_decl.concrete_ty, opaque_defn_ty)?);

// concrete_is_opaque is `true` when we're using an existential
// type without 'revealing' it. For example, code like this:
//
// existential type Foo: Debug;
// fn foo1() -> Foo { ... }
// fn foo2() -> Foo { foo1() }
//
// In `foo2`, we're not revealing the type of `Foo` - we're
// just treating it as the opaque type.
//
// When this occurs, we do *not* want to try to equate
// the concrete type with the underlying defining type
// of the existential type - this will always fail, since
// the defining type of an existential type is always
// some other type (e.g. not itself)
// Essentially, none of the normal obligations apply here -
// we're just passing around some unknown opaque type,
// without actually looking at the underlying type it
// gets 'revealed' into

if !concrete_is_opaque {
obligations.add(infcx
.at(&ObligationCause::dummy(), param_env)
.eq(opaque_decl.concrete_ty, opaque_defn_ty)?);
}
}

debug!("eq_opaque_type_and_type: equated");
Expand Down
75 changes: 41 additions & 34 deletions src/librustc_mir/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,41 +535,48 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
id: AllocId,
liveness: AllocCheck,
) -> InterpResult<'static, (Size, Align)> {
// Regular allocations.
if let Ok(alloc) = self.get(id) {
return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
}
// Function pointers.
if let Ok(_) = self.get_fn_alloc(id) {
return if let AllocCheck::Dereferencable = liveness {
// The caller requested no function pointers.
err!(DerefFunctionPointer)
} else {
Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
};
}
// Foreign statics.
// Can't do this in the match argument, we may get cycle errors since the lock would
// be held throughout the match.
let alloc = self.tcx.alloc_map.lock().get(id);
match alloc {
Some(GlobalAlloc::Static(did)) => {
assert!(self.tcx.is_foreign_item(did));
// Use size and align of the type
let ty = self.tcx.type_of(did);
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
return Ok((layout.size, layout.align.abi));
// Don't use `self.get` here as that will
// a) cause cycles in case `id` refers to a static
// b) duplicate a static's allocation in miri
match self.alloc_map.get_or(id, || Err(())) {
Ok((_, alloc)) => Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
Err(()) => {
// Not a local allocation, check the global `tcx.alloc_map`.

// Can't do this in the match argument, we may get cycle errors since the lock would
// be held throughout the match.
let alloc = self.tcx.alloc_map.lock().get(id);
match alloc {
Some(GlobalAlloc::Static(did)) => {
// Use size and align of the type.
let ty = self.tcx.type_of(did);
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
Ok((layout.size, layout.align.abi))
},
Some(GlobalAlloc::Memory(alloc)) =>
// Need to duplicate the logic here, because the global allocations have
// different associated types than the interpreter-local ones.
Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
Some(GlobalAlloc::Function(_)) => {
if let AllocCheck::Dereferencable = liveness {
// The caller requested no function pointers.
err!(DerefFunctionPointer)
} else {
Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
}
},
// The rest must be dead.
None => if let AllocCheck::MaybeDead = liveness {
// Deallocated pointers are allowed, we should be able to find
// them in the map.
Ok(*self.dead_alloc_map.get(&id)
.expect("deallocated pointers should all be recorded in \
`dead_alloc_map`"))
} else {
err!(DanglingPointerDeref)
},
}
}
_ => {}
}
// The rest must be dead.
if let AllocCheck::MaybeDead = liveness {
// Deallocated pointers are allowed, we should be able to find
// them in the map.
Ok(*self.dead_alloc_map.get(&id)
.expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
} else {
err!(DanglingPointerDeref)
}
}

Expand Down
20 changes: 10 additions & 10 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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>,

Expand All @@ -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,
Expand All @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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.
Expand Down
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)
}
Expand Down
Loading

0 comments on commit a5e7bb3

Please sign in to comment.