Auto merge of #63043 - Centril:rollup-f4baee4, r=Centril
Rollup of 6 pull requests Successful merges: - #62423 (Fix cycle error with existential types) - #62979 (Cleanup save-analysis JsonDumper) - #62982 (Don't access a static just for its size and alignment) - #63013 (add `repr(transparent)` to `IoSliceMut` where missing) - #63014 (Stop bare trait lint applying to macro call sites) - #63036 (Add lib section to rustc_lexer's Cargo.toml) Failed merges: r? @ghost
This commit is contained in:
commit
a5e7bb3e2b
@ -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(
|
||||
|
@ -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"
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
}
|
||||
pub fn to_output(self, f: impl FnOnce(&Analysis)) {
|
||||
f(&self.result)
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: DumpOutput> Drop for JsonDumper<O> {
|
||||
fn drop(&mut self) {
|
||||
self.output.dump(&self.result);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b, O: DumpOutput + 'b> JsonDumper<O> {
|
||||
impl Dumper {
|
||||
pub fn crate_prelude(&mut self, data: CratePreludeData) {
|
||||
self.result.prelude = Some(data)
|
||||
}
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,36 +453,43 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
|
||||
def_id, opaque_defn, instantiated_ty, span);
|
||||
|
||||
let mut skip_add = false;
|
||||
|
||||
if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.sty {
|
||||
if def_id == defin_ty_def_id {
|
||||
// Concrete type resolved to the existential type itself.
|
||||
// Force a cycle error.
|
||||
// FIXME(oli-obk): we could just not insert it into `concrete_existential_types`
|
||||
// which simply would make this use not a defining use.
|
||||
self.tcx().at(span).type_of(defin_ty_def_id);
|
||||
debug!("Skipping adding concrete definition for opaque type {:?} {:?}",
|
||||
opaque_defn, defin_ty_def_id);
|
||||
skip_add = true;
|
||||
}
|
||||
}
|
||||
|
||||
if !opaque_defn.substs.has_local_value() {
|
||||
let new = ty::ResolvedOpaqueTy {
|
||||
concrete_type: definition_ty,
|
||||
substs: opaque_defn.substs,
|
||||
};
|
||||
// We only want to add an entry into `concrete_existential_types`
|
||||
// if we actually found a defining usage of this existential type.
|
||||
// Otherwise, we do nothing - we'll either find a defining usage
|
||||
// in some other location, or we'll end up emitting an error due
|
||||
// to the lack of defining usage
|
||||
if !skip_add {
|
||||
let new = ty::ResolvedOpaqueTy {
|
||||
concrete_type: definition_ty,
|
||||
substs: opaque_defn.substs,
|
||||
};
|
||||
|
||||
let old = self.tables
|
||||
.concrete_existential_types
|
||||
.insert(def_id, new);
|
||||
if let Some(old) = old {
|
||||
if old.concrete_type != definition_ty || old.substs != opaque_defn.substs {
|
||||
span_bug!(
|
||||
span,
|
||||
"visit_opaque_types tried to write \
|
||||
different types for the same existential type: {:?}, {:?}, {:?}, {:?}",
|
||||
def_id,
|
||||
definition_ty,
|
||||
opaque_defn,
|
||||
old,
|
||||
);
|
||||
let old = self.tables
|
||||
.concrete_existential_types
|
||||
.insert(def_id, new);
|
||||
if let Some(old) = old {
|
||||
if old.concrete_type != definition_ty || old.substs != opaque_defn.substs {
|
||||
span_bug!(
|
||||
span,
|
||||
"visit_opaque_types tried to write different types for the same \
|
||||
existential type: {:?}, {:?}, {:?}, {:?}",
|
||||
def_id,
|
||||
definition_ty,
|
||||
opaque_defn,
|
||||
old,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -29,6 +29,7 @@ impl<'a> IoSlice<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct IoSliceMut<'a> {
|
||||
vec: iovec,
|
||||
_p: PhantomData<&'a mut [u8]>,
|
||||
|
@ -29,6 +29,7 @@ impl<'a> IoSlice<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct IoSliceMut<'a> {
|
||||
vec: __wasi_iovec_t,
|
||||
_p: PhantomData<&'a mut [u8]>,
|
||||
|
@ -29,6 +29,7 @@ impl<'a> IoSlice<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct IoSliceMut<'a> {
|
||||
vec: c::WSABUF,
|
||||
_p: PhantomData<&'a mut [u8]>,
|
||||
|
11
src/test/ui/consts/static-cycle-error.rs
Normal file
11
src/test/ui/consts/static-cycle-error.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// check-pass
|
||||
|
||||
struct Foo {
|
||||
foo: Option<&'static Foo>
|
||||
}
|
||||
|
||||
static FOO: Foo = Foo {
|
||||
foo: Some(&FOO),
|
||||
};
|
||||
|
||||
fn main() {}
|
@ -1,7 +1,7 @@
|
||||
#![feature(existential_type)]
|
||||
|
||||
existential type Foo: Fn() -> Foo;
|
||||
//~^ ERROR: cycle detected when processing `Foo`
|
||||
//~^ ERROR: could not find defining uses
|
||||
|
||||
fn crash(x: Foo) -> Foo {
|
||||
x
|
||||
|
@ -1,30 +1,8 @@
|
||||
error[E0391]: cycle detected when processing `Foo`
|
||||
error: could not find defining uses
|
||||
--> $DIR/existential-types-with-cycle-error.rs:3:1
|
||||
|
|
||||
LL | existential type Foo: Fn() -> Foo;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires processing `crash`...
|
||||
--> $DIR/existential-types-with-cycle-error.rs:6:25
|
||||
|
|
||||
LL | fn crash(x: Foo) -> Foo {
|
||||
| _________________________^
|
||||
LL | | x
|
||||
LL | | }
|
||||
| |_^
|
||||
= note: ...which again requires processing `Foo`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/existential-types-with-cycle-error.rs:1:1
|
||||
|
|
||||
LL | / #![feature(existential_type)]
|
||||
LL | |
|
||||
LL | | existential type Foo: Fn() -> Foo;
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
@ -5,7 +5,7 @@ pub trait Bar<T> {
|
||||
}
|
||||
|
||||
existential type Foo: Bar<Foo, Item = Foo>;
|
||||
//~^ ERROR: cycle detected when processing `Foo`
|
||||
//~^ ERROR: could not find defining uses
|
||||
|
||||
fn crash(x: Foo) -> Foo {
|
||||
x
|
||||
|
@ -1,30 +1,8 @@
|
||||
error[E0391]: cycle detected when processing `Foo`
|
||||
error: could not find defining uses
|
||||
--> $DIR/existential-types-with-cycle-error2.rs:7:1
|
||||
|
|
||||
LL | existential type Foo: Bar<Foo, Item = Foo>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires processing `crash`...
|
||||
--> $DIR/existential-types-with-cycle-error2.rs:10:25
|
||||
|
|
||||
LL | fn crash(x: Foo) -> Foo {
|
||||
| _________________________^
|
||||
LL | | x
|
||||
LL | | }
|
||||
| |_^
|
||||
= note: ...which again requires processing `Foo`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/existential-types-with-cycle-error2.rs:1:1
|
||||
|
|
||||
LL | / #![feature(existential_type)]
|
||||
LL | |
|
||||
LL | | pub trait Bar<T> {
|
||||
LL | | type Item;
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
20
src/test/ui/existential_types/existential_type_const.rs
Normal file
20
src/test/ui/existential_types/existential_type_const.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(existential_type)]
|
||||
// Currently, the `existential_type` feature implicitly
|
||||
// depends on `impl_trait_in_bindings` in order to work properly.
|
||||
// Specifically, this line requires `impl_trait_in_bindings` to be enabled:
|
||||
// https://github.com/rust-lang/rust/blob/481068a707679257e2a738b40987246e0420e787/src/librustc_typeck/check/mod.rs#L856
|
||||
#![feature(impl_trait_in_bindings)]
|
||||
//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash
|
||||
|
||||
// Ensures that `const` items can constrain an `existential type`.
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub existential type Foo: Debug;
|
||||
|
||||
const _FOO: Foo = 5;
|
||||
|
||||
fn main() {
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/existential_type_const.rs:8:12
|
||||
|
|
||||
LL | #![feature(impl_trait_in_bindings)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
27
src/test/ui/existential_types/existential_type_fns.rs
Normal file
27
src/test/ui/existential_types/existential_type_fns.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(existential_type)]
|
||||
|
||||
// Regression test for issue #61863
|
||||
|
||||
pub trait MyTrait {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MyStruct {
|
||||
v: u64
|
||||
}
|
||||
|
||||
impl MyTrait for MyStruct {}
|
||||
|
||||
pub fn bla() -> TE {
|
||||
return MyStruct {v:1}
|
||||
}
|
||||
|
||||
pub fn bla2() -> TE {
|
||||
bla()
|
||||
}
|
||||
|
||||
|
||||
existential type TE: MyTrait;
|
||||
|
||||
fn main() {}
|
33
src/test/ui/existential_types/existential_type_tuple.rs
Normal file
33
src/test/ui/existential_types/existential_type_tuple.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(existential_type)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub trait MyTrait {}
|
||||
|
||||
impl MyTrait for bool {}
|
||||
|
||||
struct Blah {
|
||||
my_foo: Foo,
|
||||
my_u8: u8
|
||||
}
|
||||
|
||||
impl Blah {
|
||||
fn new() -> Blah {
|
||||
Blah {
|
||||
my_foo: make_foo(),
|
||||
my_u8: 12
|
||||
}
|
||||
}
|
||||
fn into_inner(self) -> (Foo, u8) {
|
||||
(self.my_foo, self.my_u8)
|
||||
}
|
||||
}
|
||||
|
||||
fn make_foo() -> Foo {
|
||||
true
|
||||
}
|
||||
|
||||
existential type Foo: MyTrait;
|
||||
|
||||
fn main() {}
|
@ -1,9 +1,9 @@
|
||||
// Issue 52985: Cause cycle error if user code provides no use case that allows an existential type
|
||||
// to be inferred to a concrete type. This results in an infinite cycle during type normalization.
|
||||
// Issue 52985: user code provides no use case that allows an existential type
|
||||
// We now emit a 'could not find defining uses' error
|
||||
|
||||
#![feature(existential_type)]
|
||||
|
||||
existential type Foo: Copy; //~ cycle detected
|
||||
existential type Foo: Copy; //~ could not find defining uses
|
||||
|
||||
// make compiler happy about using 'Foo'
|
||||
fn bar(x: Foo) -> Foo { x }
|
||||
|
@ -1,27 +1,8 @@
|
||||
error[E0391]: cycle detected when processing `Foo`
|
||||
error: could not find defining uses
|
||||
--> $DIR/no_inferrable_concrete_type.rs:6:1
|
||||
|
|
||||
LL | existential type Foo: Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires processing `bar`...
|
||||
--> $DIR/no_inferrable_concrete_type.rs:9:23
|
||||
|
|
||||
LL | fn bar(x: Foo) -> Foo { x }
|
||||
| ^^^^^
|
||||
= note: ...which again requires processing `Foo`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/no_inferrable_concrete_type.rs:4:1
|
||||
|
|
||||
LL | / #![feature(existential_type)]
|
||||
LL | |
|
||||
LL | | existential type Foo: Copy;
|
||||
LL | |
|
||||
... |
|
||||
LL | | let _: Foo = std::mem::transmute(0u8);
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
40
src/test/ui/suggestions/auxiliary/issue-61963-1.rs
Normal file
40
src/test/ui/suggestions/auxiliary/issue-61963-1.rs
Normal file
@ -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
src/test/ui/suggestions/auxiliary/issue-61963.rs
Normal file
41
src/test/ui/suggestions/auxiliary/issue-61963.rs
Normal file
@ -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
src/test/ui/suggestions/issue-61963.rs
Normal file
24
src/test/ui/suggestions/issue-61963.rs
Normal file
@ -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
src/test/ui/suggestions/issue-61963.stderr
Normal file
14
src/test/ui/suggestions/issue-61963.stderr
Normal file
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user