mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 10:45:18 +00:00
Auto merge of #85734 - Dylan-DPC:rollup-q6iiees, r=Dylan-DPC
Rollup of 8 pull requests Successful merges: - #84221 (E0599 suggestions and elision of generic argument if no canditate is found) - #84701 (stabilize member constraints) - #85564 ( readd capture disjoint fields gate) - #85583 (Get rid of PreviousDepGraph.) - #85649 (Update cc) - #85689 (Remove Iterator #[rustc_on_unimplemented]s that no longer apply.) - #85719 (Add inline attr to CString::into_inner so it can optimize out NonNull checks) - #85725 (Remove unneeded workaround) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c4ec606606
@ -441,9 +441,9 @@ version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.67"
|
||||
version = "1.0.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
|
@ -9,7 +9,7 @@ test = false
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.2.1"
|
||||
cc = "1.0.67"
|
||||
cc = "1.0.68"
|
||||
itertools = "0.9"
|
||||
tracing = "0.1"
|
||||
libc = "0.2.50"
|
||||
@ -24,7 +24,7 @@ rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_apfloat = { path = "../rustc_apfloat" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures"}
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fs_util = { path = "../rustc_fs_util" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
|
@ -285,6 +285,8 @@ declare_features! (
|
||||
(accepted, extended_key_value_attributes, "1.54.0", Some(78835), None),
|
||||
/// Allows unsizing coercions in `const fn`.
|
||||
(accepted, const_fn_unsize, "1.54.0", Some(64992), None),
|
||||
/// Allows `impl Trait` with multiple unrelated lifetimes.
|
||||
(accepted, member_constraints, "1.54.0", Some(61997), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: accepted features
|
||||
|
@ -472,9 +472,6 @@ declare_features! (
|
||||
/// Allows explicit discriminants on non-unit enum variants.
|
||||
(active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
|
||||
|
||||
/// Allows `impl Trait` with multiple unrelated lifetimes.
|
||||
(active, member_constraints, "1.37.0", Some(61997), None),
|
||||
|
||||
/// Allows `async || body` closures.
|
||||
(active, async_closure, "1.37.0", Some(62290), None),
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::definitions::DefPathTable;
|
||||
use rustc_middle::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
|
||||
use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
|
||||
use rustc_middle::ty::query::OnDiskCache;
|
||||
use rustc_serialize::opaque::Decoder;
|
||||
use rustc_serialize::Decodable;
|
||||
@ -22,8 +22,8 @@ pub enum LoadResult<T> {
|
||||
Error { message: String },
|
||||
}
|
||||
|
||||
impl LoadResult<(PreviousDepGraph, WorkProductMap)> {
|
||||
pub fn open(self, sess: &Session) -> (PreviousDepGraph, WorkProductMap) {
|
||||
impl LoadResult<(SerializedDepGraph, WorkProductMap)> {
|
||||
pub fn open(self, sess: &Session) -> (SerializedDepGraph, WorkProductMap) {
|
||||
match self {
|
||||
LoadResult::Error { message } => {
|
||||
sess.warn(&message);
|
||||
@ -84,7 +84,7 @@ impl<T> MaybeAsync<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub type DepGraphFuture = MaybeAsync<LoadResult<(PreviousDepGraph, WorkProductMap)>>;
|
||||
pub type DepGraphFuture = MaybeAsync<LoadResult<(SerializedDepGraph, WorkProductMap)>>;
|
||||
|
||||
/// Launch a thread and load the dependency graph in the background.
|
||||
pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
||||
@ -185,7 +185,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
||||
let dep_graph = SerializedDepGraph::decode(&mut decoder)
|
||||
.expect("Error reading cached dep-graph");
|
||||
|
||||
LoadResult::Ok { data: (PreviousDepGraph::new(dep_graph), prev_work_products) }
|
||||
LoadResult::Ok { data: (dep_graph, prev_work_products) }
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::join;
|
||||
use rustc_middle::dep_graph::{DepGraph, PreviousDepGraph, WorkProduct, WorkProductId};
|
||||
use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||
use rustc_serialize::Encodable as RustcEncodable;
|
||||
@ -186,7 +186,7 @@ fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeR
|
||||
|
||||
pub fn build_dep_graph(
|
||||
sess: &Session,
|
||||
prev_graph: PreviousDepGraph,
|
||||
prev_graph: SerializedDepGraph,
|
||||
prev_work_products: FxHashMap<WorkProductId, WorkProduct>,
|
||||
) -> Option<DepGraph> {
|
||||
if sess.opts.incremental.is_none() {
|
||||
|
@ -13,4 +13,4 @@ libc = "0.2.73"
|
||||
|
||||
[build-dependencies]
|
||||
build_helper = { path = "../../src/build_helper" }
|
||||
cc = "1.0.67"
|
||||
cc = "1.0.68"
|
||||
|
@ -18,7 +18,6 @@ crate use dep_node::{make_compile_codegen_unit, make_compile_mono_item};
|
||||
pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
|
||||
pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
|
||||
pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery<DepKind>;
|
||||
pub type PreviousDepGraph = rustc_query_system::dep_graph::PreviousDepGraph<DepKind>;
|
||||
pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>;
|
||||
pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter<DepKind>;
|
||||
|
||||
|
@ -15,9 +15,9 @@ use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
|
||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
|
||||
|
||||
use super::{
|
||||
alloc_range, mir_assign_valid_types, AllocId, AllocMap, AllocRef, AllocRefMut, Allocation,
|
||||
ConstAlloc, ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy,
|
||||
Operand, Pointer, PointerArithmetic, Scalar, ScalarMaybeUninit,
|
||||
alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, ConstAlloc, ImmTy, Immediate,
|
||||
InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer,
|
||||
PointerArithmetic, Scalar, ScalarMaybeUninit,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
||||
@ -292,8 +292,6 @@ where
|
||||
// FIXME: Working around https://github.com/rust-lang/rust/issues/54385
|
||||
Tag: Debug + Copy + Eq + Hash + 'static,
|
||||
M: Machine<'mir, 'tcx, PointerTag = Tag>,
|
||||
// FIXME: Working around https://github.com/rust-lang/rust/issues/24159
|
||||
M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKind>, Allocation<Tag, M::AllocExtra>)>,
|
||||
{
|
||||
/// Take a value, which represents a (thin or wide) reference, and make it a place.
|
||||
/// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`.
|
||||
|
@ -185,21 +185,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// match x { _ => () } // fake read of `x`
|
||||
// };
|
||||
// ```
|
||||
for (thir_place, cause, hir_id) in fake_reads.into_iter() {
|
||||
let place_builder =
|
||||
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
|
||||
//
|
||||
// FIXME(RFC2229, rust#85435): Remove feature gate once diagnostics are
|
||||
// improved and unsafe checking works properly in closure bodies again.
|
||||
if this.tcx.features().capture_disjoint_fields {
|
||||
for (thir_place, cause, hir_id) in fake_reads.into_iter() {
|
||||
let place_builder =
|
||||
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
|
||||
|
||||
if let Ok(place_builder_resolved) =
|
||||
place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
|
||||
{
|
||||
let mir_place =
|
||||
place_builder_resolved.into_place(this.tcx, this.typeck_results);
|
||||
this.cfg.push_fake_read(
|
||||
block,
|
||||
this.source_info(this.tcx.hir().span(*hir_id)),
|
||||
*cause,
|
||||
mir_place,
|
||||
);
|
||||
if let Ok(place_builder_resolved) =
|
||||
place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
|
||||
{
|
||||
let mir_place =
|
||||
place_builder_resolved.into_place(this.tcx, this.typeck_results);
|
||||
this.cfg.push_fake_read(
|
||||
block,
|
||||
this.source_info(this.tcx.hir().span(*hir_id)),
|
||||
*cause,
|
||||
mir_place,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,8 @@ use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::sync::atomic::Ordering::Relaxed;
|
||||
|
||||
use super::prev::PreviousDepGraph;
|
||||
use super::query::DepGraphQuery;
|
||||
use super::serialized::{GraphEncoder, SerializedDepNodeIndex};
|
||||
use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex};
|
||||
use super::{DepContext, DepKind, DepNode, HasDepContext, WorkProductId};
|
||||
use crate::query::QueryContext;
|
||||
|
||||
@ -78,7 +77,7 @@ struct DepGraphData<K: DepKind> {
|
||||
|
||||
/// The dep-graph from the previous compilation session. It contains all
|
||||
/// nodes and edges as well as all fingerprints of nodes that have them.
|
||||
previous: PreviousDepGraph<K>,
|
||||
previous: SerializedDepGraph<K>,
|
||||
|
||||
colors: DepNodeColorMap,
|
||||
|
||||
@ -109,7 +108,7 @@ where
|
||||
|
||||
impl<K: DepKind> DepGraph<K> {
|
||||
pub fn new(
|
||||
prev_graph: PreviousDepGraph<K>,
|
||||
prev_graph: SerializedDepGraph<K>,
|
||||
prev_work_products: FxHashMap<WorkProductId, WorkProduct>,
|
||||
encoder: FileEncoder,
|
||||
record_graph: bool,
|
||||
@ -857,7 +856,7 @@ rustc_index::newtype_index! {
|
||||
/// For this reason, we avoid storing `DepNode`s more than once as map
|
||||
/// keys. The `new_node_to_index` map only contains nodes not in the previous
|
||||
/// graph, and we map nodes in the previous graph to indices via a two-step
|
||||
/// mapping. `PreviousDepGraph` maps from `DepNode` to `SerializedDepNodeIndex`,
|
||||
/// mapping. `SerializedDepGraph` maps from `DepNode` to `SerializedDepNodeIndex`,
|
||||
/// and the `prev_index_to_index` vector (which is more compact and faster than
|
||||
/// using a map) maps from `SerializedDepNodeIndex` to `DepNodeIndex`.
|
||||
///
|
||||
@ -982,7 +981,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
|
||||
fn intern_node(
|
||||
&self,
|
||||
profiler: &SelfProfilerRef,
|
||||
prev_graph: &PreviousDepGraph<K>,
|
||||
prev_graph: &SerializedDepGraph<K>,
|
||||
key: DepNode<K>,
|
||||
edges: EdgesVec,
|
||||
fingerprint: Option<Fingerprint>,
|
||||
@ -1080,7 +1079,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
|
||||
fn promote_node_and_deps_to_current(
|
||||
&self,
|
||||
profiler: &SelfProfilerRef,
|
||||
prev_graph: &PreviousDepGraph<K>,
|
||||
prev_graph: &SerializedDepGraph<K>,
|
||||
prev_index: SerializedDepNodeIndex,
|
||||
) -> DepNodeIndex {
|
||||
self.debug_assert_not_in_new_nodes(prev_graph, prev_index);
|
||||
@ -1112,7 +1111,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
|
||||
#[inline]
|
||||
fn debug_assert_not_in_new_nodes(
|
||||
&self,
|
||||
prev_graph: &PreviousDepGraph<K>,
|
||||
prev_graph: &SerializedDepGraph<K>,
|
||||
prev_index: SerializedDepNodeIndex,
|
||||
) {
|
||||
let node = &prev_graph.index_to_node(prev_index);
|
||||
|
@ -1,13 +1,11 @@
|
||||
pub mod debug;
|
||||
mod dep_node;
|
||||
mod graph;
|
||||
mod prev;
|
||||
mod query;
|
||||
mod serialized;
|
||||
|
||||
pub use dep_node::{DepNode, DepNodeParams, WorkProductId};
|
||||
pub use graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct};
|
||||
pub use prev::PreviousDepGraph;
|
||||
pub use query::DepGraphQuery;
|
||||
pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex};
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
|
||||
use super::{DepKind, DepNode};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PreviousDepGraph<K: DepKind> {
|
||||
data: SerializedDepGraph<K>,
|
||||
index: FxHashMap<DepNode<K>, SerializedDepNodeIndex>,
|
||||
}
|
||||
|
||||
impl<K: DepKind> Default for PreviousDepGraph<K> {
|
||||
fn default() -> Self {
|
||||
PreviousDepGraph { data: Default::default(), index: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: DepKind> PreviousDepGraph<K> {
|
||||
pub fn new(data: SerializedDepGraph<K>) -> PreviousDepGraph<K> {
|
||||
let index: FxHashMap<_, _> =
|
||||
data.nodes.iter_enumerated().map(|(idx, &dep_node)| (dep_node, idx)).collect();
|
||||
PreviousDepGraph { data, index }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn edge_targets_from(
|
||||
&self,
|
||||
dep_node_index: SerializedDepNodeIndex,
|
||||
) -> &[SerializedDepNodeIndex] {
|
||||
self.data.edge_targets_from(dep_node_index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode<K> {
|
||||
self.data.nodes[dep_node_index]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn node_to_index_opt(&self, dep_node: &DepNode<K>) -> Option<SerializedDepNodeIndex> {
|
||||
self.index.get(dep_node).cloned()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fingerprint_of(&self, dep_node: &DepNode<K>) -> Option<Fingerprint> {
|
||||
self.index.get(dep_node).map(|&node_index| self.data.fingerprints[node_index])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fingerprint_by_index(&self, dep_node_index: SerializedDepNodeIndex) -> Fingerprint {
|
||||
self.data.fingerprints[dep_node_index]
|
||||
}
|
||||
|
||||
pub fn node_count(&self) -> usize {
|
||||
self.index.len()
|
||||
}
|
||||
}
|
@ -37,17 +37,19 @@ rustc_index::newtype_index! {
|
||||
#[derive(Debug)]
|
||||
pub struct SerializedDepGraph<K: DepKind> {
|
||||
/// The set of all DepNodes in the graph
|
||||
pub nodes: IndexVec<SerializedDepNodeIndex, DepNode<K>>,
|
||||
nodes: IndexVec<SerializedDepNodeIndex, DepNode<K>>,
|
||||
/// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
|
||||
/// the DepNode at the same index in the nodes vector.
|
||||
pub fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>,
|
||||
fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>,
|
||||
/// For each DepNode, stores the list of edges originating from that
|
||||
/// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
|
||||
/// which holds the actual DepNodeIndices of the target nodes.
|
||||
pub edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>,
|
||||
edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>,
|
||||
/// A flattened list of all edge targets in the graph. Edge sources are
|
||||
/// implicit in edge_list_indices.
|
||||
pub edge_list_data: Vec<SerializedDepNodeIndex>,
|
||||
edge_list_data: Vec<SerializedDepNodeIndex>,
|
||||
/// Reciprocal map to `nodes`.
|
||||
index: FxHashMap<DepNode<K>, SerializedDepNodeIndex>,
|
||||
}
|
||||
|
||||
impl<K: DepKind> Default for SerializedDepGraph<K> {
|
||||
@ -57,6 +59,7 @@ impl<K: DepKind> Default for SerializedDepGraph<K> {
|
||||
fingerprints: Default::default(),
|
||||
edge_list_indices: Default::default(),
|
||||
edge_list_data: Default::default(),
|
||||
index: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -67,6 +70,30 @@ impl<K: DepKind> SerializedDepGraph<K> {
|
||||
let targets = self.edge_list_indices[source];
|
||||
&self.edge_list_data[targets.0 as usize..targets.1 as usize]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode<K> {
|
||||
self.nodes[dep_node_index]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn node_to_index_opt(&self, dep_node: &DepNode<K>) -> Option<SerializedDepNodeIndex> {
|
||||
self.index.get(dep_node).cloned()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fingerprint_of(&self, dep_node: &DepNode<K>) -> Option<Fingerprint> {
|
||||
self.index.get(dep_node).map(|&node_index| self.fingerprints[node_index])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fingerprint_by_index(&self, dep_node_index: SerializedDepNodeIndex) -> Fingerprint {
|
||||
self.fingerprints[dep_node_index]
|
||||
}
|
||||
|
||||
pub fn node_count(&self) -> usize {
|
||||
self.index.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>>
|
||||
@ -121,7 +148,10 @@ impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data })
|
||||
let index: FxHashMap<_, _> =
|
||||
nodes.iter_enumerated().map(|(idx, &dep_node)| (dep_node, idx)).collect();
|
||||
|
||||
Ok(SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data, index })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,15 +140,6 @@ pub trait InferCtxtExt<'tcx> {
|
||||
first_own_region_index: usize,
|
||||
);
|
||||
|
||||
/*private*/
|
||||
fn member_constraint_feature_gate(
|
||||
&self,
|
||||
opaque_defn: &OpaqueTypeDecl<'tcx>,
|
||||
opaque_type_def_id: DefId,
|
||||
conflict1: ty::Region<'tcx>,
|
||||
conflict2: ty::Region<'tcx>,
|
||||
) -> bool;
|
||||
|
||||
fn infer_opaque_definition_from_instantiation(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
@ -490,9 +481,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
// ['a, 'b, 'c]`, where `'a..'c` are the
|
||||
// regions that appear in the impl trait.
|
||||
|
||||
// For now, enforce a feature gate outside of async functions.
|
||||
self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_region);
|
||||
|
||||
return self.generate_member_constraint(
|
||||
concrete_ty,
|
||||
opaque_defn,
|
||||
@ -559,60 +547,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Member constraints are presently feature-gated except for
|
||||
/// async-await. We expect to lift this once we've had a bit more
|
||||
/// time.
|
||||
fn member_constraint_feature_gate(
|
||||
&self,
|
||||
opaque_defn: &OpaqueTypeDecl<'tcx>,
|
||||
opaque_type_def_id: DefId,
|
||||
conflict1: ty::Region<'tcx>,
|
||||
conflict2: ty::Region<'tcx>,
|
||||
) -> bool {
|
||||
// If we have `#![feature(member_constraints)]`, no problems.
|
||||
if self.tcx.features().member_constraints {
|
||||
return false;
|
||||
}
|
||||
|
||||
let span = self.tcx.def_span(opaque_type_def_id);
|
||||
|
||||
// Without a feature-gate, we only generate member-constraints for async-await.
|
||||
let context_name = match opaque_defn.origin {
|
||||
// No feature-gate required for `async fn`.
|
||||
hir::OpaqueTyOrigin::AsyncFn => return false,
|
||||
|
||||
// Otherwise, generate the label we'll use in the error message.
|
||||
hir::OpaqueTyOrigin::Binding
|
||||
| hir::OpaqueTyOrigin::FnReturn
|
||||
| hir::OpaqueTyOrigin::TyAlias
|
||||
| hir::OpaqueTyOrigin::Misc => "impl Trait",
|
||||
};
|
||||
let msg = format!("ambiguous lifetime bound in `{}`", context_name);
|
||||
let mut err = self.tcx.sess.struct_span_err(span, &msg);
|
||||
|
||||
let conflict1_name = conflict1.to_string();
|
||||
let conflict2_name = conflict2.to_string();
|
||||
let label_owned;
|
||||
let label = match (&*conflict1_name, &*conflict2_name) {
|
||||
("'_", "'_") => "the elided lifetimes here do not outlive one another",
|
||||
_ => {
|
||||
label_owned = format!(
|
||||
"neither `{}` nor `{}` outlives the other",
|
||||
conflict1_name, conflict2_name,
|
||||
);
|
||||
&label_owned
|
||||
}
|
||||
};
|
||||
err.span_label(span, label);
|
||||
|
||||
if self.tcx.sess.is_nightly_build() {
|
||||
err.help("add #![feature(member_constraints)] to the crate attributes to enable");
|
||||
}
|
||||
|
||||
err.emit();
|
||||
true
|
||||
}
|
||||
|
||||
/// Given the fully resolved, instantiated type for an opaque
|
||||
/// type, i.e., the value of an inference variable like C1 or C2
|
||||
/// (*), computes the "definition type" for an opaque type
|
||||
|
@ -383,6 +383,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return None;
|
||||
} else {
|
||||
span = item_name.span;
|
||||
|
||||
// Don't show generic arguments when the method can't be found in any implementation (#81576).
|
||||
let mut ty_str_reported = ty_str.clone();
|
||||
if let ty::Adt(_, ref generics) = actual.kind() {
|
||||
if generics.len() > 0 {
|
||||
let mut autoderef = self.autoderef(span, actual);
|
||||
let candidate_found = autoderef.any(|(ty, _)| {
|
||||
if let ty::Adt(ref adt_deref, _) = ty.kind() {
|
||||
self.tcx
|
||||
.inherent_impls(adt_deref.did)
|
||||
.iter()
|
||||
.filter_map(|def_id| {
|
||||
self.associated_item(
|
||||
*def_id,
|
||||
item_name,
|
||||
Namespace::ValueNS,
|
||||
)
|
||||
})
|
||||
.count()
|
||||
>= 1
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
let has_deref = autoderef.step_count() > 0;
|
||||
if !candidate_found
|
||||
&& !has_deref
|
||||
&& unsatisfied_predicates.is_empty()
|
||||
{
|
||||
if let Some((path_string, _)) = ty_str.split_once('<') {
|
||||
ty_str_reported = path_string.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
@ -391,7 +427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
item_kind,
|
||||
item_name,
|
||||
actual.prefix_string(self.tcx),
|
||||
ty_str,
|
||||
ty_str_reported,
|
||||
);
|
||||
if let Mode::MethodCall = mode {
|
||||
if let SelfSource::MethodCall(call) = source {
|
||||
@ -449,6 +485,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let mut label_span_not_found = || {
|
||||
if unsatisfied_predicates.is_empty() {
|
||||
err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
|
||||
if let ty::Adt(ref adt, _) = rcvr_ty.kind() {
|
||||
let mut inherent_impls_candidate = self
|
||||
.tcx
|
||||
.inherent_impls(adt.did)
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|def_id| {
|
||||
if let Some(assoc) =
|
||||
self.associated_item(*def_id, item_name, Namespace::ValueNS)
|
||||
{
|
||||
// Check for both mode is the same so we avoid suggesting
|
||||
// incorrect associated item.
|
||||
match (mode, assoc.fn_has_self_parameter, source) {
|
||||
(Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
|
||||
// We check that the suggest type is actually
|
||||
// different from the received one
|
||||
// So we avoid suggestion method with Box<Self>
|
||||
// for instance
|
||||
self.tcx.at(span).type_of(*def_id) != actual
|
||||
&& self.tcx.at(span).type_of(*def_id) != rcvr_ty
|
||||
}
|
||||
(Mode::Path, false, _) => true,
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if inherent_impls_candidate.len() > 0 {
|
||||
inherent_impls_candidate.sort();
|
||||
inherent_impls_candidate.dedup();
|
||||
|
||||
// number of type to shows at most.
|
||||
let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
|
||||
let type_candidates = inherent_impls_candidate
|
||||
.iter()
|
||||
.take(limit)
|
||||
.map(|impl_item| {
|
||||
format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let additional_types = if inherent_impls_candidate.len() > limit {
|
||||
format!(
|
||||
"\nand {} more types",
|
||||
inherent_impls_candidate.len() - limit
|
||||
)
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
err.note(&format!(
|
||||
"the {item_kind} was found for\n{}{}",
|
||||
type_candidates, additional_types
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
|
||||
}
|
||||
|
@ -25,40 +25,6 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
|
||||
/// [impl]: crate::iter#implementing-iterator
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
_Self = "[std::ops::Range<Idx>; 1]",
|
||||
label = "if you meant to iterate between two values, remove the square brackets",
|
||||
note = "`[start..end]` is an array of one `Range`; you might have meant to have a `Range` \
|
||||
without the brackets: `start..end`"
|
||||
),
|
||||
on(
|
||||
_Self = "[std::ops::RangeFrom<Idx>; 1]",
|
||||
label = "if you meant to iterate from a value onwards, remove the square brackets",
|
||||
note = "`[start..]` is an array of one `RangeFrom`; you might have meant to have a \
|
||||
`RangeFrom` without the brackets: `start..`, keeping in mind that iterating over an \
|
||||
unbounded iterator will run forever unless you `break` or `return` from within the \
|
||||
loop"
|
||||
),
|
||||
on(
|
||||
_Self = "[std::ops::RangeTo<Idx>; 1]",
|
||||
label = "if you meant to iterate until a value, remove the square brackets and add a \
|
||||
starting value",
|
||||
note = "`[..end]` is an array of one `RangeTo`; you might have meant to have a bounded \
|
||||
`Range` without the brackets: `0..end`"
|
||||
),
|
||||
on(
|
||||
_Self = "[std::ops::RangeInclusive<Idx>; 1]",
|
||||
label = "if you meant to iterate between two values, remove the square brackets",
|
||||
note = "`[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a \
|
||||
`RangeInclusive` without the brackets: `start..=end`"
|
||||
),
|
||||
on(
|
||||
_Self = "[std::ops::RangeToInclusive<Idx>; 1]",
|
||||
label = "if you meant to iterate until a value (including it), remove the square brackets \
|
||||
and add a starting value",
|
||||
note = "`[..=end]` is an array of one `RangeToInclusive`; you might have meant to have a \
|
||||
bounded `RangeInclusive` without the brackets: `0..=end`"
|
||||
),
|
||||
on(
|
||||
_Self = "std::ops::RangeTo<Idx>",
|
||||
label = "if you meant to iterate until a value, add a starting value",
|
||||
|
@ -14,4 +14,4 @@ core = { path = "../core" }
|
||||
compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] }
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0.67"
|
||||
cc = "1.0.68"
|
||||
|
@ -672,6 +672,7 @@ impl CString {
|
||||
}
|
||||
|
||||
/// Bypass "move out of struct which implements [`Drop`] trait" restriction.
|
||||
#[inline]
|
||||
fn into_inner(self) -> Box<[u8]> {
|
||||
// Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)`
|
||||
// so we use `ManuallyDrop` to ensure `self` is not dropped.
|
||||
|
@ -21,7 +21,7 @@ compiler_builtins = "0.1.0"
|
||||
cfg-if = "0.1.8"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0.67"
|
||||
cc = "1.0.68"
|
||||
|
||||
[features]
|
||||
llvm-libunwind = []
|
||||
|
@ -40,7 +40,7 @@ cmake = "0.1.38"
|
||||
filetime = "0.2"
|
||||
num_cpus = "1.0"
|
||||
getopts = "0.2.19"
|
||||
cc = "1.0.67"
|
||||
cc = "1.0.68"
|
||||
libc = "0.2"
|
||||
serde = { version = "1.0.8", features = ["derive"] }
|
||||
serde_json = "1.0.2"
|
||||
|
@ -1,29 +0,0 @@
|
||||
# `member_constraints`
|
||||
|
||||
The tracking issue for this feature is: [#61997]
|
||||
|
||||
[#61997]: https://github.com/rust-lang/rust/issues/61997
|
||||
|
||||
------------------------
|
||||
|
||||
The `member_constraints` feature gate lets you use `impl Trait` syntax with
|
||||
multiple unrelated lifetime parameters.
|
||||
|
||||
A simple example is:
|
||||
|
||||
```rust
|
||||
#![feature(member_constraints)]
|
||||
|
||||
trait Trait<'a, 'b> { }
|
||||
impl<T> Trait<'_, '_> for T {}
|
||||
|
||||
fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
|
||||
(x, y)
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
```
|
||||
|
||||
Without the `member_constraints` feature gate, the above example is an
|
||||
error because both `'a` and `'b` appear in the impl Trait bounds, but
|
||||
neither outlives the other.
|
@ -1,10 +1,9 @@
|
||||
// edition:2018
|
||||
// run-pass
|
||||
|
||||
// Test that a feature gate is needed to use `impl Trait` as the
|
||||
// return type of an async.
|
||||
|
||||
#![feature(member_constraints)]
|
||||
// Test member constraints that appear in the `impl Trait`
|
||||
// return type of an async function.
|
||||
// (This used to require a feature gate.)
|
||||
|
||||
trait Trait<'a, 'b> { }
|
||||
impl<T> Trait<'_, '_> for T { }
|
||||
|
@ -1,20 +0,0 @@
|
||||
// edition:2018
|
||||
|
||||
// Test that a feature gate is needed to use `impl Trait` as the
|
||||
// return type of an async.
|
||||
|
||||
trait Trait<'a, 'b> { }
|
||||
impl<T> Trait<'_, '_> for T { }
|
||||
|
||||
async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
//~^ ERROR ambiguous lifetime bound
|
||||
//~| ERROR ambiguous lifetime bound
|
||||
//~| ERROR ambiguous lifetime bound
|
||||
//~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
//~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
(a, b)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = async_ret_impl_trait(&22, &44);
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
error: ambiguous lifetime bound in `impl Trait`
|
||||
--> $DIR/ret-impl-trait-no-fg.rs:9:64
|
||||
|
|
||||
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
|
||||
|
|
||||
= help: add #![feature(member_constraints)] to the crate attributes to enable
|
||||
|
||||
error: ambiguous lifetime bound in `impl Trait`
|
||||
--> $DIR/ret-impl-trait-no-fg.rs:9:64
|
||||
|
|
||||
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
|
||||
|
|
||||
= help: add #![feature(member_constraints)] to the crate attributes to enable
|
||||
|
||||
error: ambiguous lifetime bound in `impl Trait`
|
||||
--> $DIR/ret-impl-trait-no-fg.rs:9:64
|
||||
|
|
||||
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^ the elided lifetimes here do not outlive one another
|
||||
|
|
||||
= help: add #![feature(member_constraints)] to the crate attributes to enable
|
||||
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ret-impl-trait-no-fg.rs:9:1
|
||||
|
|
||||
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: hidden type `(&u8, &u8)` captures lifetime '_#5r
|
||||
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ret-impl-trait-no-fg.rs:9:1
|
||||
|
|
||||
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: hidden type `(&u8, &u8)` captures lifetime '_#6r
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0700`.
|
@ -1,5 +1,5 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/ret-impl-trait-one.rs:12:80
|
||||
--> $DIR/ret-impl-trait-one.rs:10:80
|
||||
|
|
||||
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
|
||||
| ________________________________--__--__________________________________________^
|
||||
|
@ -3,8 +3,6 @@
|
||||
// Test that a feature gate is needed to use `impl Trait` as the
|
||||
// return type of an async.
|
||||
|
||||
#![feature(member_constraints)]
|
||||
|
||||
trait Trait<'a> { }
|
||||
impl<T> Trait<'_> for T { }
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/ret-impl-trait-one.rs:12:65
|
||||
--> $DIR/ret-impl-trait-one.rs:10:65
|
||||
|
|
||||
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
|
||||
| ------ ^^^^^^^^^^^^^^
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0599]: no method named `closure` found for struct `Obj<[closure@$DIR/issue-18343.rs:6:28: 6:33]>` in the current scope
|
||||
error[E0599]: no method named `closure` found for struct `Obj` in the current scope
|
||||
--> $DIR/issue-18343.rs:7:7
|
||||
|
|
||||
LL | struct Obj<F> where F: FnMut() -> u32 {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0599]: no method named `closure` found for struct `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
|
||||
error[E0599]: no method named `closure` found for struct `Obj` in the current scope
|
||||
--> $DIR/issue-2392.rs:36:15
|
||||
|
|
||||
LL | struct Obj<F> where F: FnOnce() -> u32 {
|
||||
@ -12,7 +12,7 @@ help: to call the function stored in `closure`, surround the field access with p
|
||||
LL | (o_closure.closure)();
|
||||
| ^ ^
|
||||
|
||||
error[E0599]: no method named `not_closure` found for struct `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
|
||||
error[E0599]: no method named `not_closure` found for struct `Obj` in the current scope
|
||||
--> $DIR/issue-2392.rs:38:15
|
||||
|
|
||||
LL | struct Obj<F> where F: FnOnce() -> u32 {
|
||||
@ -23,7 +23,7 @@ LL | o_closure.not_closure();
|
||||
| |
|
||||
| field, not a method
|
||||
|
||||
error[E0599]: no method named `closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
|
||||
error[E0599]: no method named `closure` found for struct `Obj` in the current scope
|
||||
--> $DIR/issue-2392.rs:42:12
|
||||
|
|
||||
LL | struct Obj<F> where F: FnOnce() -> u32 {
|
||||
@ -65,7 +65,7 @@ help: to call the function stored in `boxed_closure`, surround the field access
|
||||
LL | (boxed_closure.boxed_closure)();
|
||||
| ^ ^
|
||||
|
||||
error[E0599]: no method named `closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
|
||||
error[E0599]: no method named `closure` found for struct `Obj` in the current scope
|
||||
--> $DIR/issue-2392.rs:53:12
|
||||
|
|
||||
LL | struct Obj<F> where F: FnOnce() -> u32 {
|
||||
@ -79,7 +79,7 @@ help: to call the function stored in `closure`, surround the field access with p
|
||||
LL | (w.wrap.closure)();
|
||||
| ^ ^
|
||||
|
||||
error[E0599]: no method named `not_closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
|
||||
error[E0599]: no method named `not_closure` found for struct `Obj` in the current scope
|
||||
--> $DIR/issue-2392.rs:55:12
|
||||
|
|
||||
LL | struct Obj<F> where F: FnOnce() -> u32 {
|
||||
@ -90,7 +90,7 @@ LL | w.wrap.not_closure();
|
||||
| |
|
||||
| field, not a method
|
||||
|
||||
error[E0599]: no method named `closure` found for struct `Obj<Box<(dyn FnOnce() -> u32 + 'static)>>` in the current scope
|
||||
error[E0599]: no method named `closure` found for struct `Obj` in the current scope
|
||||
--> $DIR/issue-2392.rs:58:24
|
||||
|
|
||||
LL | struct Obj<F> where F: FnOnce() -> u32 {
|
||||
|
@ -1,10 +0,0 @@
|
||||
trait Trait<'a, 'b> {}
|
||||
impl<T> Trait<'_, '_> for T {}
|
||||
|
||||
fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
|
||||
//~^ ERROR ambiguous lifetime bound
|
||||
//~| ERROR ambiguous lifetime bound
|
||||
(x, y)
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,18 +0,0 @@
|
||||
error: ambiguous lifetime bound in `impl Trait`
|
||||
--> $DIR/feature-gate-member-constraints.rs:4:43
|
||||
|
|
||||
LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
|
||||
|
|
||||
= help: add #![feature(member_constraints)] to the crate attributes to enable
|
||||
|
||||
error: ambiguous lifetime bound in `impl Trait`
|
||||
--> $DIR/feature-gate-member-constraints.rs:4:43
|
||||
|
|
||||
LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^ the elided lifetimes here do not outlive one another
|
||||
|
|
||||
= help: add #![feature(member_constraints)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/error-handling.rs:6:32
|
||||
--> $DIR/error-handling.rs:5:32
|
||||
|
|
||||
LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -8,7 +8,7 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
|
||||
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/error-handling.rs:26:16
|
||||
--> $DIR/error-handling.rs:25:16
|
||||
|
|
||||
LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
|
||||
| -- -- lifetime `'b` defined here
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/error-handling.rs:26:16
|
||||
--> $DIR/error-handling.rs:25:16
|
||||
|
|
||||
LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
|
||||
| -- -- lifetime `'b` defined here
|
||||
|
@ -1,6 +1,5 @@
|
||||
// compile-flags:-Zborrowck=mir
|
||||
|
||||
#![feature(member_constraints)]
|
||||
// revisions: min_tait full_tait
|
||||
#![feature(min_type_alias_impl_trait)]
|
||||
#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
|
||||
|
@ -3,8 +3,6 @@
|
||||
// revisions: migrate mir
|
||||
//[mir]compile-flags: -Z borrowck=mir
|
||||
|
||||
#![feature(member_constraints)]
|
||||
|
||||
trait Trait<'a, 'b> {}
|
||||
impl<T> Trait<'_, '_> for T {}
|
||||
|
||||
|
@ -3,10 +3,8 @@
|
||||
// revisions: migrate mir
|
||||
//[mir]compile-flags: -Z borrowck=mir
|
||||
|
||||
#![feature(member_constraints)]
|
||||
|
||||
trait Trait<'a, 'b> { }
|
||||
impl<T> Trait<'_, '_> for T { }
|
||||
trait Trait<'a, 'b> {}
|
||||
impl<T> Trait<'_, '_> for T {}
|
||||
|
||||
// Test case where we have elision in the impl trait and we have to
|
||||
// pick the right region.
|
||||
@ -26,4 +24,4 @@ fn upper_bounds3<'b>(a: &u8) -> impl Trait<'_, 'b> {
|
||||
(a, a)
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
@ -3,10 +3,9 @@
|
||||
// revisions: migrate mir
|
||||
//[mir]compile-flags: -Z borrowck=mir
|
||||
|
||||
#![feature(member_constraints)]
|
||||
#![feature(min_type_alias_impl_trait)]
|
||||
trait Trait<'a, 'b> { }
|
||||
impl<T> Trait<'_, '_> for T { }
|
||||
trait Trait<'a, 'b> {}
|
||||
impl<T> Trait<'_, '_> for T {}
|
||||
|
||||
// Here we wind up selecting `'a` and `'b` in the hidden type because
|
||||
// those are the types that appear in the original values.
|
||||
@ -28,4 +27,4 @@ fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> Foo<'a, 'b> {
|
||||
(a, b)
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
@ -3,10 +3,8 @@
|
||||
// revisions: migrate mir
|
||||
//[mir]compile-flags: -Z borrowck=mir
|
||||
|
||||
#![feature(member_constraints)]
|
||||
|
||||
trait Trait<'a, 'b> { }
|
||||
impl<T> Trait<'_, '_> for T { }
|
||||
trait Trait<'a, 'b> {}
|
||||
impl<T> Trait<'_, '_> for T {}
|
||||
|
||||
// Here we wind up selecting `'a` and `'b` in the hidden type because
|
||||
// those are the types that appear in the original values.
|
||||
@ -26,4 +24,4 @@ fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
(a, b)
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
@ -3,8 +3,6 @@
|
||||
// revisions: migrate mir
|
||||
//[mir]compile-flags: -Z borrowck=mir
|
||||
|
||||
#![feature(member_constraints)]
|
||||
|
||||
trait Trait<'a, 'b> {}
|
||||
impl<T> Trait<'_, '_> for T {}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ordinary-bounds-unrelated.rs:18:74
|
||||
--> $DIR/ordinary-bounds-unrelated.rs:16:74
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,7 +1,5 @@
|
||||
// edition:2018
|
||||
|
||||
#![feature(member_constraints)]
|
||||
|
||||
trait Trait<'a, 'b> {}
|
||||
impl<T> Trait<'_, '_> for T {}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ordinary-bounds-unrelated.rs:18:74
|
||||
--> $DIR/ordinary-bounds-unrelated.rs:16:74
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body
|
||||
--> $DIR/ordinary-bounds-unrelated.rs:18:74
|
||||
--> $DIR/ordinary-bounds-unrelated.rs:16:74
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ordinary-bounds-unsuited.rs:20:62
|
||||
--> $DIR/ordinary-bounds-unsuited.rs:18:62
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,7 +1,5 @@
|
||||
// edition:2018
|
||||
|
||||
#![feature(member_constraints)]
|
||||
|
||||
trait Trait<'a, 'b> {}
|
||||
impl<T> Trait<'_, '_> for T {}
|
||||
|
||||
@ -18,7 +16,7 @@ struct Ordinary<'a>(&'a u8);
|
||||
// consider the loans for both `'a` and `'b` alive.
|
||||
|
||||
fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
|
||||
//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
{
|
||||
// We return a value:
|
||||
//
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ordinary-bounds-unsuited.rs:20:62
|
||||
--> $DIR/ordinary-bounds-unsuited.rs:18:62
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body
|
||||
--> $DIR/ordinary-bounds-unsuited.rs:20:62
|
||||
--> $DIR/ordinary-bounds-unsuited.rs:18:62
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,7 +1,5 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(member_constraints)]
|
||||
|
||||
trait MultiRegionTrait<'a, 'b> {}
|
||||
impl<'a, 'b> MultiRegionTrait<'a, 'b> for (&'a u32, &'b u32) {}
|
||||
|
||||
|
@ -3,6 +3,9 @@ error[E0599]: no function or associated item named `new_undirected` found for st
|
||||
|
|
||||
LL | let ug = Graph::<i32, i32>::new_undirected();
|
||||
| ^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph<i32, i32>`
|
||||
|
|
||||
= note: the function or associated item was found for
|
||||
- `issue_30123_aux::Graph<N, E, Undirected>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0599]: no method named `iter` found for struct `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` in the current scope
|
||||
error[E0599]: no method named `iter` found for struct `Iterate` in the current scope
|
||||
--> $DIR/issue-41880.rs:27:24
|
||||
|
|
||||
LL | pub struct Iterate<T, F> {
|
||||
|
106
src/test/ui/methods/method-not-found-generic-arg-elision.rs
Normal file
106
src/test/ui/methods/method-not-found-generic-arg-elision.rs
Normal file
@ -0,0 +1,106 @@
|
||||
// Test for issue 81576
|
||||
// Remove generic arguments if no method is found for all possible generic argument
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Wrapper2<'a, T, const C: usize> {
|
||||
x: &'a T,
|
||||
}
|
||||
|
||||
impl<'a, const C: usize> Wrapper2<'a, i8, C> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl<'a, const C: usize> Wrapper2<'a, i16, C> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl<'a, const C: usize> Wrapper2<'a, i32, C> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
struct Wrapper<T>(T);
|
||||
|
||||
impl Wrapper<i8> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl Wrapper<i16> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl Wrapper<i32> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl Wrapper<i64> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl Wrapper<u8> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl Wrapper<u16> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
struct Point<T> {
|
||||
x: T,
|
||||
y: T,
|
||||
}
|
||||
|
||||
impl Point<f64> {
|
||||
fn distance(&self) -> f64 {
|
||||
self.x.hypot(self.y)
|
||||
}
|
||||
}
|
||||
|
||||
struct Other;
|
||||
|
||||
impl Other {
|
||||
fn other(&self) {}
|
||||
}
|
||||
|
||||
struct Struct<T>{
|
||||
_phatom: PhantomData<T>
|
||||
}
|
||||
|
||||
impl<T> Default for Struct<T> {
|
||||
fn default() -> Self {
|
||||
Self{ _phatom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Copy + PartialEq + Eq + PartialOrd + Ord> Struct<T> {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let point_f64 = Point{ x: 1_f64, y: 1_f64};
|
||||
let d = point_f64.distance();
|
||||
let point_i32 = Point{ x: 1_i32, y: 1_i32};
|
||||
let d = point_i32.distance();
|
||||
//~^ ERROR no method named `distance` found for struct `Point<i32>
|
||||
let d = point_i32.other();
|
||||
//~^ ERROR no method named `other` found for struct `Point
|
||||
let v = vec![1_i32, 2, 3];
|
||||
v.iter().map(|x| x * x).extend(std::iter::once(100));
|
||||
//~^ ERROR no method named `extend` found for struct `Map
|
||||
let wrapper = Wrapper(true);
|
||||
wrapper.method();
|
||||
//~^ ERROR no method named `method` found for struct `Wrapper<bool>
|
||||
wrapper.other();
|
||||
//~^ ERROR no method named `other` found for struct `Wrapper
|
||||
let boolean = true;
|
||||
let wrapper = Wrapper2::<'_, _, 3> {x: &boolean};
|
||||
wrapper.method();
|
||||
//~^ ERROR no method named `method` found for struct `Wrapper2<'_, bool, 3_usize>
|
||||
wrapper.other();
|
||||
//~^ ERROR no method named `other` found for struct `Wrapper2
|
||||
let a = vec![1, 2, 3];
|
||||
a.not_found();
|
||||
//~^ ERROR no method named `not_found` found for struct `Vec
|
||||
let s = Struct::<f64>::default();
|
||||
s.method();
|
||||
//~^ ERROR the method `method` exists for struct `Struct<f64>`, but its trait bounds were not satisfied
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
error[E0599]: no method named `distance` found for struct `Point<i32>` in the current scope
|
||||
--> $DIR/method-not-found-generic-arg-elision.rs:82:23
|
||||
|
|
||||
LL | struct Point<T> {
|
||||
| --------------- method `distance` not found for this
|
||||
...
|
||||
LL | let d = point_i32.distance();
|
||||
| ^^^^^^^^ method not found in `Point<i32>`
|
||||
|
|
||||
= note: the method was found for
|
||||
- `Point<f64>`
|
||||
|
||||
error[E0599]: no method named `other` found for struct `Point` in the current scope
|
||||
--> $DIR/method-not-found-generic-arg-elision.rs:84:23
|
||||
|
|
||||
LL | struct Point<T> {
|
||||
| --------------- method `other` not found for this
|
||||
...
|
||||
LL | let d = point_i32.other();
|
||||
| ^^^^^ method not found in `Point<i32>`
|
||||
|
||||
error[E0599]: no method named `extend` found for struct `Map` in the current scope
|
||||
--> $DIR/method-not-found-generic-arg-elision.rs:87:29
|
||||
|
|
||||
LL | v.iter().map(|x| x * x).extend(std::iter::once(100));
|
||||
| ^^^^^^ method not found in `Map<std::slice::Iter<'_, i32>, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:27]>`
|
||||
|
||||
error[E0599]: no method named `method` found for struct `Wrapper<bool>` in the current scope
|
||||
--> $DIR/method-not-found-generic-arg-elision.rs:90:13
|
||||
|
|
||||
LL | struct Wrapper<T>(T);
|
||||
| --------------------- method `method` not found for this
|
||||
...
|
||||
LL | wrapper.method();
|
||||
| ^^^^^^ method not found in `Wrapper<bool>`
|
||||
|
|
||||
= note: the method was found for
|
||||
- `Wrapper<i8>`
|
||||
- `Wrapper<i16>`
|
||||
- `Wrapper<i32>`
|
||||
- `Wrapper<i64>`
|
||||
and 2 more types
|
||||
|
||||
error[E0599]: no method named `other` found for struct `Wrapper` in the current scope
|
||||
--> $DIR/method-not-found-generic-arg-elision.rs:92:13
|
||||
|
|
||||
LL | struct Wrapper<T>(T);
|
||||
| --------------------- method `other` not found for this
|
||||
...
|
||||
LL | wrapper.other();
|
||||
| ^^^^^ method not found in `Wrapper<bool>`
|
||||
|
||||
error[E0599]: no method named `method` found for struct `Wrapper2<'_, bool, 3_usize>` in the current scope
|
||||
--> $DIR/method-not-found-generic-arg-elision.rs:96:13
|
||||
|
|
||||
LL | struct Wrapper2<'a, T, const C: usize> {
|
||||
| -------------------------------------- method `method` not found for this
|
||||
...
|
||||
LL | wrapper.method();
|
||||
| ^^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>`
|
||||
|
|
||||
= note: the method was found for
|
||||
- `Wrapper2<'a, i8, C>`
|
||||
- `Wrapper2<'a, i16, C>`
|
||||
- `Wrapper2<'a, i32, C>`
|
||||
|
||||
error[E0599]: no method named `other` found for struct `Wrapper2` in the current scope
|
||||
--> $DIR/method-not-found-generic-arg-elision.rs:98:13
|
||||
|
|
||||
LL | struct Wrapper2<'a, T, const C: usize> {
|
||||
| -------------------------------------- method `other` not found for this
|
||||
...
|
||||
LL | wrapper.other();
|
||||
| ^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>`
|
||||
|
||||
error[E0599]: no method named `not_found` found for struct `Vec<{integer}>` in the current scope
|
||||
--> $DIR/method-not-found-generic-arg-elision.rs:101:7
|
||||
|
|
||||
LL | a.not_found();
|
||||
| ^^^^^^^^^ method not found in `Vec<{integer}>`
|
||||
|
||||
error[E0599]: the method `method` exists for struct `Struct<f64>`, but its trait bounds were not satisfied
|
||||
--> $DIR/method-not-found-generic-arg-elision.rs:104:7
|
||||
|
|
||||
LL | struct Struct<T>{
|
||||
| ---------------- method `method` not found for this
|
||||
...
|
||||
LL | s.method();
|
||||
| ^^^^^^ method cannot be called on `Struct<f64>` due to unsatisfied trait bounds
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`f64: Eq`
|
||||
`f64: Ord`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
@ -1,5 +1,5 @@
|
||||
warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-74761.rs:4:32
|
||||
--> $DIR/issue-74761.rs:3:32
|
||||
|
|
||||
LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -8,13 +8,13 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
|
||||
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
|
||||
|
||||
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/issue-74761.rs:11:6
|
||||
--> $DIR/issue-74761.rs:10:6
|
||||
|
|
||||
LL | impl<'a, 'b> A for () {
|
||||
| ^^ unconstrained lifetime parameter
|
||||
|
||||
error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/issue-74761.rs:11:10
|
||||
--> $DIR/issue-74761.rs:10:10
|
||||
|
|
||||
LL | impl<'a, 'b> A for () {
|
||||
| ^^ unconstrained lifetime parameter
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/issue-74761.rs:11:6
|
||||
--> $DIR/issue-74761.rs:10:6
|
||||
|
|
||||
LL | impl<'a, 'b> A for () {
|
||||
| ^^ unconstrained lifetime parameter
|
||||
|
||||
error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/issue-74761.rs:11:10
|
||||
--> $DIR/issue-74761.rs:10:10
|
||||
|
|
||||
LL | impl<'a, 'b> A for () {
|
||||
| ^^ unconstrained lifetime parameter
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![feature(member_constraints)]
|
||||
// revisions: min_tait full_tait
|
||||
#![feature(min_type_alias_impl_trait)]
|
||||
#![cfg_attr(full_tait, feature(type_alias_impl_trait))]
|
||||
|
@ -0,0 +1,27 @@
|
||||
// check-pass
|
||||
// revisions: mir thir
|
||||
// [thir]compile-flags: -Z thir-unsafeck
|
||||
|
||||
// This is issue #85435. But the real story is reflected in issue #85561, where
|
||||
// a bug in the implementation of feature(capture_disjoint_fields) () was
|
||||
// exposed to non-feature-gated code by a diagnostic changing PR that removed
|
||||
// the gating in one case.
|
||||
|
||||
// This test is double-checking that the case of interest continues to work as
|
||||
// expected in the *absence* of that feature gate. At the time of this writing,
|
||||
// enabling the feature gate will cause this test to fail. We obviously cannot
|
||||
// stabilize that feature until it can correctly handle this test.
|
||||
|
||||
fn main() {
|
||||
let val: u8 = 5;
|
||||
let u8_ptr: *const u8 = &val;
|
||||
let _closure = || {
|
||||
unsafe {
|
||||
let tmp = *u8_ptr;
|
||||
tmp
|
||||
|
||||
// Just dereferencing and returning directly compiles fine:
|
||||
// *u8_ptr
|
||||
}
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user