mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
Auto merge of #105760 - matthiaskrgr:rollup-r8beo9w, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #105481 (Start improving monomorphization items stats) - #105674 (Point at method chains on `E0271` errors) - #105679 (Suggest constraining type parameter with `Clone`) - #105694 (Don't create dummy if val has escaping bounds var) - #105727 (Tweak output for bare `dyn Trait` in arguments) - #105739 (Migrate Jump to def links background to CSS variable) - #105743 (`SimplifiedType` cleanups) - #105758 (Move `TypeckResults` to separate module) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7a6af2711b
@ -21,3 +21,6 @@ monomorphize_large_assignments =
|
||||
moving {$size} bytes
|
||||
.label = value moved from here
|
||||
.note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
|
||||
|
||||
monomorphize_couldnt_dump_mono_stats =
|
||||
unexpected error occurred while dumping monomorphization stats: {$error}
|
||||
|
@ -13,7 +13,9 @@ use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_infer::infer;
|
||||
use rustc_infer::traits::{self, StatementAsExpression};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, Ty};
|
||||
use rustc_middle::ty::{
|
||||
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
|
||||
};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
@ -1276,15 +1278,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
|
||||
// Check that we're in fact trying to clone into the expected type
|
||||
&& self.can_coerce(*pointee_ty, expected_ty)
|
||||
&& let trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty]))
|
||||
// And the expected type doesn't implement `Clone`
|
||||
&& !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
|
||||
self.tcx,
|
||||
traits::ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
ty::Binder::dummy(self.tcx.mk_trait_ref(
|
||||
clone_trait_did,
|
||||
[expected_ty],
|
||||
)),
|
||||
trait_ref,
|
||||
))
|
||||
{
|
||||
diag.span_note(
|
||||
@ -1293,6 +1293,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
"`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead"
|
||||
),
|
||||
);
|
||||
let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id);
|
||||
if let ty::Param(param) = expected_ty.kind()
|
||||
&& let Some(generics) = self.tcx.hir().get_generics(owner)
|
||||
{
|
||||
suggest_constraining_type_params(
|
||||
self.tcx,
|
||||
generics,
|
||||
diag,
|
||||
vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
|
||||
);
|
||||
} else {
|
||||
self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
|
||||
use rustc_middle::traits::util::supertraits;
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
|
||||
use rustc_middle::ty::print::with_crate_prefix;
|
||||
use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
|
||||
use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
@ -270,7 +270,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
|
||||
let ty_str = self.ty_to_string(rcvr_ty);
|
||||
let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
|
||||
let is_method = mode == Mode::MethodCall;
|
||||
let item_kind = if is_method {
|
||||
"method"
|
||||
@ -563,7 +563,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let term = pred.skip_binder().term;
|
||||
|
||||
let obligation = format!("{} = {}", projection_ty, term);
|
||||
let quiet = format!("{} = {}", quiet_projection_ty, term);
|
||||
let quiet = with_forced_trimmed_paths!(format!(
|
||||
"{} = {}",
|
||||
quiet_projection_ty, term
|
||||
));
|
||||
|
||||
bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
|
||||
Some((obligation, projection_ty.self_ty()))
|
||||
@ -573,7 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let self_ty = p.self_ty();
|
||||
let path = p.print_only_trait_path();
|
||||
let obligation = format!("{}: {}", self_ty, path);
|
||||
let quiet = format!("_: {}", path);
|
||||
let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
|
||||
bound_span_label(self_ty, &obligation, &quiet);
|
||||
Some((obligation, self_ty))
|
||||
}
|
||||
@ -796,7 +799,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
(None, None)
|
||||
};
|
||||
let primary_message = primary_message.unwrap_or_else(|| format!(
|
||||
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
|
||||
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
|
||||
but its trait bounds were not satisfied"
|
||||
));
|
||||
err.set_primary_message(&primary_message);
|
||||
if let Some(label) = label {
|
||||
@ -1848,7 +1852,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.suggest_derive(err, &preds);
|
||||
}
|
||||
|
||||
fn suggest_derive(
|
||||
pub fn suggest_derive(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
unsatisfied_predicates: &[(
|
||||
|
@ -200,6 +200,15 @@ impl<'tcx> MonoItem<'tcx> {
|
||||
MonoItem::GlobalAsm(..) => LOCAL_CRATE,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the item's `DefId`
|
||||
pub fn def_id(&self) -> DefId {
|
||||
match *self {
|
||||
MonoItem::Fn(Instance { def, .. }) => def.def_id(),
|
||||
MonoItem::Static(def_id) => def_id,
|
||||
MonoItem::GlobalAsm(item_id) => item_id.owner_id.to_def_id(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for MonoItem<'tcx> {
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
use crate::arena::Arena;
|
||||
use crate::dep_graph::{DepGraph, DepKindStruct};
|
||||
use crate::hir::place::Place as HirPlace;
|
||||
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
|
||||
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
|
||||
use crate::lint::struct_lint_level;
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use crate::middle::resolve_lifetime;
|
||||
@ -18,13 +17,13 @@ use crate::thir::Thir;
|
||||
use crate::traits;
|
||||
use crate::ty::query::{self, TyCtxtAt};
|
||||
use crate::ty::{
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
|
||||
ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
|
||||
GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
|
||||
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
|
||||
TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstS, DefIdTree, FloatTy, FloatVar,
|
||||
FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
|
||||
ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
|
||||
ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy,
|
||||
Visibility,
|
||||
};
|
||||
use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
|
||||
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
@ -35,25 +34,20 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal};
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_errors::{
|
||||
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LOCAL_CRATE};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_hir::hir_id::OwnerId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{
|
||||
Constness, ExprKind, HirId, ImplItemKind, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet,
|
||||
Node, TraitCandidate, TraitItemKind,
|
||||
Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
|
||||
};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::mir::FakeReadCause;
|
||||
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||
@ -75,7 +69,6 @@ use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlag
|
||||
use std::any::Any;
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_map::{self, Entry};
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter;
|
||||
@ -83,8 +76,6 @@ use std::mem;
|
||||
use std::ops::{Bound, Deref};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::{ImplPolarity, RvalueScopes};
|
||||
|
||||
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
|
||||
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
|
||||
fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
|
||||
@ -284,666 +275,6 @@ pub struct CommonConsts<'tcx> {
|
||||
pub unit: Const<'tcx>,
|
||||
}
|
||||
|
||||
pub struct LocalTableInContext<'a, V> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a ItemLocalMap<V>,
|
||||
}
|
||||
|
||||
/// Validate that the given HirId (respectively its `local_id` part) can be
|
||||
/// safely used as a key in the maps of a TypeckResults. For that to be
|
||||
/// the case, the HirId must have the same `owner` as all the other IDs in
|
||||
/// this table (signified by `hir_owner`). Otherwise the HirId
|
||||
/// would be in a different frame of reference and using its `local_id`
|
||||
/// would result in lookup errors, or worse, in silently wrong data being
|
||||
/// stored/returned.
|
||||
#[inline]
|
||||
fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
||||
if hir_id.owner != hir_owner {
|
||||
invalid_hir_id_for_typeck_results(hir_owner, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
||||
ty::tls::with(|tcx| {
|
||||
bug!(
|
||||
"node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
|
||||
tcx.hir().node_to_string(hir_id),
|
||||
hir_id.owner,
|
||||
hir_owner
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
impl<'a, V> LocalTableInContext<'a, V> {
|
||||
pub fn contains_key(&self, id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.contains_key(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn get(&self, id: hir::HirId) -> Option<&V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.get(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
|
||||
self.data.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
|
||||
type Output = V;
|
||||
|
||||
fn index(&self, key: hir::HirId) -> &V {
|
||||
self.get(key).expect("LocalTableInContext: key not found")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LocalTableInContextMut<'a, V> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a mut ItemLocalMap<V>,
|
||||
}
|
||||
|
||||
impl<'a, V> LocalTableInContextMut<'a, V> {
|
||||
pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.get_mut(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.entry(id.local_id)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.insert(id.local_id, val)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.remove(&id.local_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Whenever a value may be live across a generator yield, the type of that value winds up in the
|
||||
/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
|
||||
/// captured types that can be useful for diagnostics. In particular, it stores the span that
|
||||
/// caused a given type to be recorded, along with the scope that enclosed the value (which can
|
||||
/// be used to find the await that the value is live across).
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```ignore (pseudo-Rust)
|
||||
/// async move {
|
||||
/// let x: T = expr;
|
||||
/// foo.await
|
||||
/// ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
|
||||
/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
|
||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct GeneratorInteriorTypeCause<'tcx> {
|
||||
/// Type of the captured binding.
|
||||
pub ty: Ty<'tcx>,
|
||||
/// Span of the binding that was captured.
|
||||
pub span: Span,
|
||||
/// Span of the scope of the captured binding.
|
||||
pub scope_span: Option<Span>,
|
||||
/// Span of `.await` or `yield` expression.
|
||||
pub yield_span: Span,
|
||||
/// Expr which the type evaluated from.
|
||||
pub expr: Option<hir::HirId>,
|
||||
}
|
||||
|
||||
// This type holds diagnostic information on generators and async functions across crate boundaries
|
||||
// and is used to provide better error messages
|
||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
|
||||
pub struct GeneratorDiagnosticData<'tcx> {
|
||||
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||
pub hir_owner: DefId,
|
||||
pub nodes_types: ItemLocalMap<Ty<'tcx>>,
|
||||
pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
}
|
||||
|
||||
#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
|
||||
pub struct TypeckResults<'tcx> {
|
||||
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
|
||||
pub hir_owner: OwnerId,
|
||||
|
||||
/// Resolved definitions for `<T>::X` associated paths and
|
||||
/// method calls, including those of overloaded operators.
|
||||
type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
|
||||
|
||||
/// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
|
||||
/// or patterns (`S { field }`). The index is often useful by itself, but to learn more
|
||||
/// about the field you also need definition of the variant to which the field
|
||||
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
|
||||
field_indices: ItemLocalMap<usize>,
|
||||
|
||||
/// Stores the types for various nodes in the AST. Note that this table
|
||||
/// is not guaranteed to be populated outside inference. See
|
||||
/// typeck::check::fn_ctxt for details.
|
||||
node_types: ItemLocalMap<Ty<'tcx>>,
|
||||
|
||||
/// Stores the type parameters which were substituted to obtain the type
|
||||
/// of this node. This only applies to nodes that refer to entities
|
||||
/// parameterized by type parameters, such as generic fns, types, or
|
||||
/// other items.
|
||||
node_substs: ItemLocalMap<SubstsRef<'tcx>>,
|
||||
|
||||
/// This will either store the canonicalized types provided by the user
|
||||
/// or the substitutions that the user explicitly gave (if any) attached
|
||||
/// to `id`. These will not include any inferred values. The canonical form
|
||||
/// is used to capture things like `_` or other unspecified values.
|
||||
///
|
||||
/// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
|
||||
/// canonical substitutions would include only `for<X> { Vec<X> }`.
|
||||
///
|
||||
/// See also `AscribeUserType` statement in MIR.
|
||||
user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
|
||||
|
||||
adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
|
||||
/// Stores the actual binding mode for all instances of hir::BindingAnnotation.
|
||||
pat_binding_modes: ItemLocalMap<BindingMode>,
|
||||
|
||||
/// Stores the types which were implicitly dereferenced in pattern binding modes
|
||||
/// for later usage in THIR lowering. For example,
|
||||
///
|
||||
/// ```
|
||||
/// match &&Some(5i32) {
|
||||
/// Some(n) => {},
|
||||
/// _ => {},
|
||||
/// }
|
||||
/// ```
|
||||
/// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
|
||||
///
|
||||
/// See:
|
||||
/// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
|
||||
pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// Records the reasons that we picked the kind of each closure;
|
||||
/// not all closures are present in the map.
|
||||
closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
|
||||
|
||||
/// For each fn, records the "liberated" types of its arguments
|
||||
/// and return type. Liberated means that all bound regions
|
||||
/// (including late-bound regions) are replaced with free
|
||||
/// equivalents. This table is not used in codegen (since regions
|
||||
/// are erased there) and hence is not serialized to metadata.
|
||||
///
|
||||
/// This table also contains the "revealed" values for any `impl Trait`
|
||||
/// that appear in the signature and whose values are being inferred
|
||||
/// by this function.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::fmt::Debug;
|
||||
/// fn foo(x: &u32) -> impl Debug { *x }
|
||||
/// ```
|
||||
///
|
||||
/// The function signature here would be:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(&'a u32) -> Foo
|
||||
/// ```
|
||||
///
|
||||
/// where `Foo` is an opaque type created for this function.
|
||||
///
|
||||
///
|
||||
/// The *liberated* form of this would be
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// fn(&'a u32) -> u32
|
||||
/// ```
|
||||
///
|
||||
/// Note that `'a` is not bound (it would be an `ReFree`) and
|
||||
/// that the `Foo` opaque type is replaced by its hidden type.
|
||||
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
|
||||
|
||||
/// For each FRU expression, record the normalized types of the fields
|
||||
/// of the struct - this is needed because it is non-trivial to
|
||||
/// normalize while preserving regions. This table is used only in
|
||||
/// MIR construction and hence is not serialized to metadata.
|
||||
fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// For every coercion cast we add the HIR node ID of the cast
|
||||
/// expression to this set.
|
||||
coercion_casts: ItemLocalSet,
|
||||
|
||||
/// Set of trait imports actually used in the method resolution.
|
||||
/// This is used for warning unused imports. During type
|
||||
/// checking, this `Lrc` should not be cloned: it must have a ref-count
|
||||
/// of 1 so that we can insert things into the set mutably.
|
||||
pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
|
||||
|
||||
/// If any errors occurred while type-checking this body,
|
||||
/// this field will be set to `Some(ErrorGuaranteed)`.
|
||||
pub tainted_by_errors: Option<ErrorGuaranteed>,
|
||||
|
||||
/// All the opaque types that have hidden types set
|
||||
/// by this function. We also store the
|
||||
/// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
|
||||
/// even if they are only set in dead code (which doesn't show up in MIR).
|
||||
pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
|
||||
|
||||
/// Tracks the minimum captures required for a closure;
|
||||
/// see `MinCaptureInformationMap` for more details.
|
||||
pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
|
||||
|
||||
/// Tracks the fake reads required for a closure and the reason for the fake read.
|
||||
/// When performing pattern matching for closures, there are times we don't end up
|
||||
/// reading places that are mentioned in a closure (because of _ patterns). However,
|
||||
/// to ensure the places are initialized, we introduce fake reads.
|
||||
/// Consider these two examples:
|
||||
/// ``` (discriminant matching with only wildcard arm)
|
||||
/// let x: u8;
|
||||
/// let c = || match x { _ => () };
|
||||
/// ```
|
||||
/// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
|
||||
/// want to capture it. However, we do still want an error here, because `x` should have
|
||||
/// to be initialized at the point where c is created. Therefore, we add a "fake read"
|
||||
/// instead.
|
||||
/// ``` (destructured assignments)
|
||||
/// let c = || {
|
||||
/// let (t1, t2) = t;
|
||||
/// }
|
||||
/// ```
|
||||
/// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
|
||||
/// we never capture `t`. This becomes an issue when we build MIR as we require
|
||||
/// information on `t` in order to create place `t.0` and `t.1`. We can solve this
|
||||
/// issue by fake reading `t`.
|
||||
pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
|
||||
|
||||
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
|
||||
/// by applying extended parameter rules.
|
||||
/// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
|
||||
pub rvalue_scopes: RvalueScopes,
|
||||
|
||||
/// Stores the type, expression, span and optional scope span of all types
|
||||
/// that are live across the yield of this generator (if a generator).
|
||||
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||
|
||||
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
|
||||
/// as `&[u8]`, depending on the pattern in which they are used.
|
||||
/// This hashset records all instances where we behave
|
||||
/// like this to allow `const_to_pat` to reliably handle this situation.
|
||||
pub treat_byte_string_as_slice: ItemLocalSet,
|
||||
|
||||
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
|
||||
/// on closure size.
|
||||
pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeckResults<'tcx> {
|
||||
pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
|
||||
TypeckResults {
|
||||
hir_owner,
|
||||
type_dependent_defs: Default::default(),
|
||||
field_indices: Default::default(),
|
||||
user_provided_types: Default::default(),
|
||||
user_provided_sigs: Default::default(),
|
||||
node_types: Default::default(),
|
||||
node_substs: Default::default(),
|
||||
adjustments: Default::default(),
|
||||
pat_binding_modes: Default::default(),
|
||||
pat_adjustments: Default::default(),
|
||||
closure_kind_origins: Default::default(),
|
||||
liberated_fn_sigs: Default::default(),
|
||||
fru_field_types: Default::default(),
|
||||
coercion_casts: Default::default(),
|
||||
used_trait_imports: Lrc::new(Default::default()),
|
||||
tainted_by_errors: None,
|
||||
concrete_opaque_types: Default::default(),
|
||||
closure_min_captures: Default::default(),
|
||||
closure_fake_reads: Default::default(),
|
||||
rvalue_scopes: Default::default(),
|
||||
generator_interior_types: ty::Binder::dummy(Default::default()),
|
||||
treat_byte_string_as_slice: Default::default(),
|
||||
closure_size_eval: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
|
||||
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.res,
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
|
||||
.type_dependent_def(id)
|
||||
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_dependent_defs(
|
||||
&self,
|
||||
) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
|
||||
}
|
||||
|
||||
pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
|
||||
}
|
||||
|
||||
pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
|
||||
self.type_dependent_def(id).map(|(_, def_id)| def_id)
|
||||
}
|
||||
|
||||
pub fn type_dependent_defs_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
|
||||
}
|
||||
|
||||
pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
|
||||
}
|
||||
|
||||
pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
|
||||
}
|
||||
|
||||
pub fn field_index(&self, id: hir::HirId) -> usize {
|
||||
self.field_indices().get(id).cloned().expect("no index for a field")
|
||||
}
|
||||
|
||||
pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
|
||||
self.field_indices().get(id).cloned()
|
||||
}
|
||||
|
||||
pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
|
||||
}
|
||||
|
||||
pub fn user_provided_types_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
|
||||
}
|
||||
|
||||
pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
|
||||
}
|
||||
|
||||
pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
|
||||
}
|
||||
|
||||
pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
|
||||
let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
|
||||
vec.iter()
|
||||
.map(|item| {
|
||||
GeneratorInteriorTypeCause {
|
||||
ty: item.ty,
|
||||
span: item.span,
|
||||
scope_span: item.scope_span,
|
||||
yield_span: item.yield_span,
|
||||
expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
GeneratorDiagnosticData {
|
||||
generator_interior_types: generator_interior_type,
|
||||
hir_owner: self.hir_owner.to_def_id(),
|
||||
nodes_types: self.node_types.clone(),
|
||||
adjustments: self.adjustments.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
|
||||
self.node_type_opt(id).unwrap_or_else(|| {
|
||||
bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_types.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
|
||||
}
|
||||
|
||||
pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
|
||||
}
|
||||
|
||||
pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_substs.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
/// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
|
||||
/// doesn't provide type parameter substitutions.
|
||||
///
|
||||
/// [`expr_ty`]: TypeckResults::expr_ty
|
||||
pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
|
||||
self.node_type(pat.hir_id)
|
||||
}
|
||||
|
||||
/// Returns the type of an expression as a monotype.
|
||||
///
|
||||
/// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
|
||||
/// some cases, we insert `Adjustment` annotations such as auto-deref or
|
||||
/// auto-ref. The type returned by this function does not consider such
|
||||
/// adjustments. See `expr_ty_adjusted()` instead.
|
||||
///
|
||||
/// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
|
||||
/// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
|
||||
/// instead of `fn(ty) -> T with T = isize`.
|
||||
pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
|
||||
self.node_type(expr.hir_id)
|
||||
}
|
||||
|
||||
pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
|
||||
self.node_type_opt(expr.hir_id)
|
||||
}
|
||||
|
||||
pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
|
||||
}
|
||||
|
||||
pub fn adjustments_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
|
||||
}
|
||||
|
||||
pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
|
||||
self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
|
||||
}
|
||||
|
||||
/// Returns the type of `expr`, considering any `Adjustment`
|
||||
/// entry recorded for that expression.
|
||||
pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
|
||||
self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
|
||||
}
|
||||
|
||||
pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
|
||||
self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
|
||||
}
|
||||
|
||||
pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
|
||||
// Only paths and method calls/overloaded operators have
|
||||
// entries in type_dependent_defs, ignore the former here.
|
||||
if let hir::ExprKind::Path(_) = expr.kind {
|
||||
return false;
|
||||
}
|
||||
|
||||
matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
|
||||
}
|
||||
|
||||
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
|
||||
self.pat_binding_modes().get(id).copied().or_else(|| {
|
||||
s.delay_span_bug(sp, "missing binding mode");
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
|
||||
}
|
||||
|
||||
pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
|
||||
}
|
||||
|
||||
pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
|
||||
}
|
||||
|
||||
/// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
|
||||
/// by the closure.
|
||||
pub fn closure_min_captures_flattened(
|
||||
&self,
|
||||
closure_def_id: LocalDefId,
|
||||
) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
|
||||
self.closure_min_captures
|
||||
.get(&closure_def_id)
|
||||
.map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
|
||||
}
|
||||
|
||||
pub fn closure_kind_origins_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
|
||||
}
|
||||
|
||||
pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
|
||||
}
|
||||
|
||||
pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
|
||||
}
|
||||
|
||||
pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
|
||||
}
|
||||
|
||||
pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
|
||||
}
|
||||
|
||||
pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
|
||||
self.coercion_casts.contains(&hir_id.local_id)
|
||||
}
|
||||
|
||||
pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
|
||||
self.coercion_casts.insert(id);
|
||||
}
|
||||
|
||||
pub fn coercion_casts(&self) -> &ItemLocalSet {
|
||||
&self.coercion_casts
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
pub struct UserTypeAnnotationIndex {
|
||||
derive [HashStable]
|
||||
DEBUG_FORMAT = "UserType({})",
|
||||
const START_INDEX = 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Mapping of type annotation indices to canonical user type annotations.
|
||||
pub type CanonicalUserTypeAnnotations<'tcx> =
|
||||
IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
|
||||
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct CanonicalUserTypeAnnotation<'tcx> {
|
||||
pub user_ty: Box<CanonicalUserType<'tcx>>,
|
||||
pub span: Span,
|
||||
pub inferred_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
/// Canonicalized user type annotation.
|
||||
pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
|
||||
|
||||
impl<'tcx> CanonicalUserType<'tcx> {
|
||||
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
|
||||
/// i.e., each thing is mapped to a canonical variable with the same index.
|
||||
pub fn is_identity(&self) -> bool {
|
||||
match self.value {
|
||||
UserType::Ty(_) => false,
|
||||
UserType::TypeOf(_, user_substs) => {
|
||||
if user_substs.user_self_ty.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
|
||||
match kind.unpack() {
|
||||
GenericArgKind::Type(ty) => match ty.kind() {
|
||||
ty::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == b.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
GenericArgKind::Lifetime(r) => match *r {
|
||||
ty::ReLateBound(debruijn, br) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == br.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
GenericArgKind::Const(ct) => match ct.kind() {
|
||||
ty::ConstKind::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == b
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A user-given type annotation attached to a constant. These arise
|
||||
/// from constants that are named via paths, like `Foo::<A>::new` and
|
||||
/// so forth.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub enum UserType<'tcx> {
|
||||
Ty(Ty<'tcx>),
|
||||
|
||||
/// The canonical type is the result of `type_of(def_id)` with the
|
||||
/// given substitutions applied.
|
||||
TypeOf(DefId, UserSubsts<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> CommonTypes<'tcx> {
|
||||
fn new(
|
||||
interners: &CtxtInterners<'tcx>,
|
||||
|
@ -6,28 +6,18 @@ use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::iter;
|
||||
|
||||
use self::SimplifiedTypeGen::*;
|
||||
use self::SimplifiedType::*;
|
||||
|
||||
pub type SimplifiedType = SimplifiedTypeGen<DefId>;
|
||||
|
||||
/// See `simplify_type`
|
||||
///
|
||||
/// Note that we keep this type generic over the type of identifier it uses
|
||||
/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
|
||||
/// keys (in which case we use a DefPathHash as id-type) but in the general case
|
||||
/// the non-stable but fast to construct DefId-version is the better choice.
|
||||
/// See `simplify_type`.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
|
||||
pub enum SimplifiedTypeGen<D>
|
||||
where
|
||||
D: Copy + Debug + Eq,
|
||||
{
|
||||
pub enum SimplifiedType {
|
||||
BoolSimplifiedType,
|
||||
CharSimplifiedType,
|
||||
IntSimplifiedType(ty::IntTy),
|
||||
UintSimplifiedType(ty::UintTy),
|
||||
FloatSimplifiedType(ty::FloatTy),
|
||||
AdtSimplifiedType(D),
|
||||
ForeignSimplifiedType(D),
|
||||
AdtSimplifiedType(DefId),
|
||||
ForeignSimplifiedType(DefId),
|
||||
StrSimplifiedType,
|
||||
ArraySimplifiedType,
|
||||
SliceSimplifiedType,
|
||||
@ -38,9 +28,9 @@ where
|
||||
/// A trait object, all of whose components are markers
|
||||
/// (e.g., `dyn Send + Sync`).
|
||||
MarkerTraitObjectSimplifiedType,
|
||||
TraitSimplifiedType(D),
|
||||
ClosureSimplifiedType(D),
|
||||
GeneratorSimplifiedType(D),
|
||||
TraitSimplifiedType(DefId),
|
||||
ClosureSimplifiedType(DefId),
|
||||
GeneratorSimplifiedType(DefId),
|
||||
GeneratorWitnessSimplifiedType(usize),
|
||||
FunctionSimplifiedType(usize),
|
||||
PlaceholderSimplifiedType,
|
||||
@ -142,8 +132,8 @@ pub fn simplify_type<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
|
||||
pub fn def(self) -> Option<D> {
|
||||
impl SimplifiedType {
|
||||
pub fn def(self) -> Option<DefId> {
|
||||
match self {
|
||||
AdtSimplifiedType(d)
|
||||
| ForeignSimplifiedType(d)
|
||||
@ -153,36 +143,6 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
|
||||
where
|
||||
F: Fn(D) -> U,
|
||||
U: Copy + Debug + Eq,
|
||||
{
|
||||
match self {
|
||||
BoolSimplifiedType => BoolSimplifiedType,
|
||||
CharSimplifiedType => CharSimplifiedType,
|
||||
IntSimplifiedType(t) => IntSimplifiedType(t),
|
||||
UintSimplifiedType(t) => UintSimplifiedType(t),
|
||||
FloatSimplifiedType(t) => FloatSimplifiedType(t),
|
||||
AdtSimplifiedType(d) => AdtSimplifiedType(map(d)),
|
||||
ForeignSimplifiedType(d) => ForeignSimplifiedType(map(d)),
|
||||
StrSimplifiedType => StrSimplifiedType,
|
||||
ArraySimplifiedType => ArraySimplifiedType,
|
||||
SliceSimplifiedType => SliceSimplifiedType,
|
||||
RefSimplifiedType(m) => RefSimplifiedType(m),
|
||||
PtrSimplifiedType(m) => PtrSimplifiedType(m),
|
||||
NeverSimplifiedType => NeverSimplifiedType,
|
||||
MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
|
||||
TupleSimplifiedType(n) => TupleSimplifiedType(n),
|
||||
TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
|
||||
ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
|
||||
GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
|
||||
GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
|
||||
FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
|
||||
PlaceholderSimplifiedType => PlaceholderSimplifiedType,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given generic arguments from an obligation and an impl,
|
||||
|
@ -83,10 +83,8 @@ pub use self::consts::{
|
||||
Const, ConstInt, ConstKind, ConstS, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
|
||||
};
|
||||
pub use self::context::{
|
||||
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
||||
CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData,
|
||||
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults,
|
||||
UserType, UserTypeAnnotationIndex,
|
||||
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
|
||||
TyCtxtFeed,
|
||||
};
|
||||
pub use self::instance::{Instance, InstanceDef, ShortInstance};
|
||||
pub use self::list::List;
|
||||
@ -103,6 +101,11 @@ pub use self::sty::{
|
||||
Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
|
||||
};
|
||||
pub use self::trait_def::TraitDef;
|
||||
pub use self::typeck_results::{
|
||||
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
||||
GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
|
||||
UserTypeAnnotationIndex,
|
||||
};
|
||||
|
||||
pub mod _match;
|
||||
pub mod abstract_const;
|
||||
@ -143,6 +146,7 @@ mod parameterized;
|
||||
mod rvalue_scopes;
|
||||
mod structural_impls;
|
||||
mod sty;
|
||||
mod typeck_results;
|
||||
|
||||
// Data types
|
||||
|
||||
|
@ -1,15 +1,10 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::{DefId, DefIndex};
|
||||
use rustc_hir::def_id::DefIndex;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
|
||||
use crate::middle::exported_symbols::ExportedSymbol;
|
||||
use crate::mir::Body;
|
||||
use crate::ty::{
|
||||
self, Clause, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty,
|
||||
};
|
||||
use crate::ty;
|
||||
|
||||
pub trait ParameterizedOverTcx: 'static {
|
||||
#[allow(unused_lifetimes)]
|
||||
type Value<'tcx>;
|
||||
}
|
||||
|
||||
@ -67,7 +62,7 @@ trivially_parameterized_over_tcx! {
|
||||
ty::TraitDef,
|
||||
ty::Visibility<DefIndex>,
|
||||
ty::adjustment::CoerceUnsizedInfo,
|
||||
ty::fast_reject::SimplifiedTypeGen<DefId>,
|
||||
ty::fast_reject::SimplifiedType,
|
||||
rustc_ast::Attribute,
|
||||
rustc_ast::DelimArgs,
|
||||
rustc_attr::ConstStability,
|
||||
@ -100,29 +95,28 @@ trivially_parameterized_over_tcx! {
|
||||
rustc_type_ir::Variance,
|
||||
}
|
||||
|
||||
// HACK(compiler-errors): This macro rule can only take an ident,
|
||||
// not a path, due to parsing ambiguity reasons. That means we gotta
|
||||
// import all of these types above.
|
||||
// HACK(compiler-errors): This macro rule can only take a fake path,
|
||||
// not a real, due to parsing ambiguity reasons.
|
||||
#[macro_export]
|
||||
macro_rules! parameterized_over_tcx {
|
||||
($($ident:ident),+ $(,)?) => {
|
||||
($($($fake_path:ident)::+),+ $(,)?) => {
|
||||
$(
|
||||
impl $crate::ty::ParameterizedOverTcx for $ident<'static> {
|
||||
type Value<'tcx> = $ident<'tcx>;
|
||||
impl $crate::ty::ParameterizedOverTcx for $($fake_path)::+<'static> {
|
||||
type Value<'tcx> = $($fake_path)::+<'tcx>;
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
parameterized_over_tcx! {
|
||||
Ty,
|
||||
FnSig,
|
||||
GenericPredicates,
|
||||
TraitRef,
|
||||
Const,
|
||||
Predicate,
|
||||
Clause,
|
||||
GeneratorDiagnosticData,
|
||||
Body,
|
||||
ExportedSymbol,
|
||||
crate::middle::exported_symbols::ExportedSymbol,
|
||||
crate::mir::Body,
|
||||
ty::Ty,
|
||||
ty::FnSig,
|
||||
ty::GenericPredicates,
|
||||
ty::TraitRef,
|
||||
ty::Const,
|
||||
ty::Predicate,
|
||||
ty::Clause,
|
||||
ty::GeneratorDiagnosticData,
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ use rustc_session::config::TrimmedDefPaths;
|
||||
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::FileNameDisplayPreference;
|
||||
use rustc_target::abi::Size;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use smallvec::SmallVec;
|
||||
@ -818,11 +819,16 @@ pub trait PrettyPrinter<'tcx>:
|
||||
p!("@", print_def_path(did.to_def_id(), substs));
|
||||
} else {
|
||||
let span = self.tcx().def_span(did);
|
||||
let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
|
||||
FileNameDisplayPreference::Short
|
||||
} else {
|
||||
FileNameDisplayPreference::Remapped
|
||||
};
|
||||
p!(write(
|
||||
"@{}",
|
||||
// This may end up in stderr diagnostics but it may also be emitted
|
||||
// into MIR. Hence we use the remapped path if available
|
||||
self.tcx().sess.source_map().span_to_embeddable_string(span)
|
||||
self.tcx().sess.source_map().span_to_string(span, preference)
|
||||
));
|
||||
}
|
||||
} else {
|
||||
|
689
compiler/rustc_middle/src/ty/typeck_results.rs
Normal file
689
compiler/rustc_middle/src/ty/typeck_results.rs
Normal file
@ -0,0 +1,689 @@
|
||||
use crate::{
|
||||
hir::place::Place as HirPlace,
|
||||
infer::canonical::Canonical,
|
||||
ty::{
|
||||
self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
|
||||
GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
|
||||
},
|
||||
};
|
||||
use rustc_data_structures::{fx::FxHashMap, sync::Lrc, unord::UnordSet, vec_map::VecMap};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{
|
||||
def::{DefKind, Res},
|
||||
def_id::{DefId, LocalDefId, LocalDefIdMap},
|
||||
hir_id::OwnerId,
|
||||
HirId, ItemLocalId, ItemLocalMap, ItemLocalSet,
|
||||
};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::mir::FakeReadCause;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Span;
|
||||
use std::{
|
||||
collections::hash_map::{self, Entry},
|
||||
hash::Hash,
|
||||
iter,
|
||||
};
|
||||
|
||||
use super::RvalueScopes;
|
||||
|
||||
#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
|
||||
pub struct TypeckResults<'tcx> {
|
||||
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
|
||||
pub hir_owner: OwnerId,
|
||||
|
||||
/// Resolved definitions for `<T>::X` associated paths and
|
||||
/// method calls, including those of overloaded operators.
|
||||
type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
|
||||
|
||||
/// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
|
||||
/// or patterns (`S { field }`). The index is often useful by itself, but to learn more
|
||||
/// about the field you also need definition of the variant to which the field
|
||||
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
|
||||
field_indices: ItemLocalMap<usize>,
|
||||
|
||||
/// Stores the types for various nodes in the AST. Note that this table
|
||||
/// is not guaranteed to be populated outside inference. See
|
||||
/// typeck::check::fn_ctxt for details.
|
||||
node_types: ItemLocalMap<Ty<'tcx>>,
|
||||
|
||||
/// Stores the type parameters which were substituted to obtain the type
|
||||
/// of this node. This only applies to nodes that refer to entities
|
||||
/// parameterized by type parameters, such as generic fns, types, or
|
||||
/// other items.
|
||||
node_substs: ItemLocalMap<SubstsRef<'tcx>>,
|
||||
|
||||
/// This will either store the canonicalized types provided by the user
|
||||
/// or the substitutions that the user explicitly gave (if any) attached
|
||||
/// to `id`. These will not include any inferred values. The canonical form
|
||||
/// is used to capture things like `_` or other unspecified values.
|
||||
///
|
||||
/// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
|
||||
/// canonical substitutions would include only `for<X> { Vec<X> }`.
|
||||
///
|
||||
/// See also `AscribeUserType` statement in MIR.
|
||||
user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
|
||||
|
||||
adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
|
||||
/// Stores the actual binding mode for all instances of hir::BindingAnnotation.
|
||||
pat_binding_modes: ItemLocalMap<BindingMode>,
|
||||
|
||||
/// Stores the types which were implicitly dereferenced in pattern binding modes
|
||||
/// for later usage in THIR lowering. For example,
|
||||
///
|
||||
/// ```
|
||||
/// match &&Some(5i32) {
|
||||
/// Some(n) => {},
|
||||
/// _ => {},
|
||||
/// }
|
||||
/// ```
|
||||
/// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
|
||||
///
|
||||
/// See:
|
||||
/// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
|
||||
pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// Records the reasons that we picked the kind of each closure;
|
||||
/// not all closures are present in the map.
|
||||
closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
|
||||
|
||||
/// For each fn, records the "liberated" types of its arguments
|
||||
/// and return type. Liberated means that all bound regions
|
||||
/// (including late-bound regions) are replaced with free
|
||||
/// equivalents. This table is not used in codegen (since regions
|
||||
/// are erased there) and hence is not serialized to metadata.
|
||||
///
|
||||
/// This table also contains the "revealed" values for any `impl Trait`
|
||||
/// that appear in the signature and whose values are being inferred
|
||||
/// by this function.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::fmt::Debug;
|
||||
/// fn foo(x: &u32) -> impl Debug { *x }
|
||||
/// ```
|
||||
///
|
||||
/// The function signature here would be:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(&'a u32) -> Foo
|
||||
/// ```
|
||||
///
|
||||
/// where `Foo` is an opaque type created for this function.
|
||||
///
|
||||
///
|
||||
/// The *liberated* form of this would be
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// fn(&'a u32) -> u32
|
||||
/// ```
|
||||
///
|
||||
/// Note that `'a` is not bound (it would be an `ReFree`) and
|
||||
/// that the `Foo` opaque type is replaced by its hidden type.
|
||||
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
|
||||
|
||||
/// For each FRU expression, record the normalized types of the fields
|
||||
/// of the struct - this is needed because it is non-trivial to
|
||||
/// normalize while preserving regions. This table is used only in
|
||||
/// MIR construction and hence is not serialized to metadata.
|
||||
fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// For every coercion cast we add the HIR node ID of the cast
|
||||
/// expression to this set.
|
||||
coercion_casts: ItemLocalSet,
|
||||
|
||||
/// Set of trait imports actually used in the method resolution.
|
||||
/// This is used for warning unused imports. During type
|
||||
/// checking, this `Lrc` should not be cloned: it must have a ref-count
|
||||
/// of 1 so that we can insert things into the set mutably.
|
||||
pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
|
||||
|
||||
/// If any errors occurred while type-checking this body,
|
||||
/// this field will be set to `Some(ErrorGuaranteed)`.
|
||||
pub tainted_by_errors: Option<ErrorGuaranteed>,
|
||||
|
||||
/// All the opaque types that have hidden types set
|
||||
/// by this function. We also store the
|
||||
/// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
|
||||
/// even if they are only set in dead code (which doesn't show up in MIR).
|
||||
pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
|
||||
|
||||
/// Tracks the minimum captures required for a closure;
|
||||
/// see `MinCaptureInformationMap` for more details.
|
||||
pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
|
||||
|
||||
/// Tracks the fake reads required for a closure and the reason for the fake read.
|
||||
/// When performing pattern matching for closures, there are times we don't end up
|
||||
/// reading places that are mentioned in a closure (because of _ patterns). However,
|
||||
/// to ensure the places are initialized, we introduce fake reads.
|
||||
/// Consider these two examples:
|
||||
/// ``` (discriminant matching with only wildcard arm)
|
||||
/// let x: u8;
|
||||
/// let c = || match x { _ => () };
|
||||
/// ```
|
||||
/// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
|
||||
/// want to capture it. However, we do still want an error here, because `x` should have
|
||||
/// to be initialized at the point where c is created. Therefore, we add a "fake read"
|
||||
/// instead.
|
||||
/// ``` (destructured assignments)
|
||||
/// let c = || {
|
||||
/// let (t1, t2) = t;
|
||||
/// }
|
||||
/// ```
|
||||
/// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
|
||||
/// we never capture `t`. This becomes an issue when we build MIR as we require
|
||||
/// information on `t` in order to create place `t.0` and `t.1`. We can solve this
|
||||
/// issue by fake reading `t`.
|
||||
pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
|
||||
|
||||
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
|
||||
/// by applying extended parameter rules.
|
||||
/// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
|
||||
pub rvalue_scopes: RvalueScopes,
|
||||
|
||||
/// Stores the type, expression, span and optional scope span of all types
|
||||
/// that are live across the yield of this generator (if a generator).
|
||||
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||
|
||||
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
|
||||
/// as `&[u8]`, depending on the pattern in which they are used.
|
||||
/// This hashset records all instances where we behave
|
||||
/// like this to allow `const_to_pat` to reliably handle this situation.
|
||||
pub treat_byte_string_as_slice: ItemLocalSet,
|
||||
|
||||
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
|
||||
/// on closure size.
|
||||
pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
|
||||
}
|
||||
|
||||
/// Whenever a value may be live across a generator yield, the type of that value winds up in the
|
||||
/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
|
||||
/// captured types that can be useful for diagnostics. In particular, it stores the span that
|
||||
/// caused a given type to be recorded, along with the scope that enclosed the value (which can
|
||||
/// be used to find the await that the value is live across).
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```ignore (pseudo-Rust)
|
||||
/// async move {
|
||||
/// let x: T = expr;
|
||||
/// foo.await
|
||||
/// ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
|
||||
/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
|
||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct GeneratorInteriorTypeCause<'tcx> {
|
||||
/// Type of the captured binding.
|
||||
pub ty: Ty<'tcx>,
|
||||
/// Span of the binding that was captured.
|
||||
pub span: Span,
|
||||
/// Span of the scope of the captured binding.
|
||||
pub scope_span: Option<Span>,
|
||||
/// Span of `.await` or `yield` expression.
|
||||
pub yield_span: Span,
|
||||
/// Expr which the type evaluated from.
|
||||
pub expr: Option<hir::HirId>,
|
||||
}
|
||||
|
||||
// This type holds diagnostic information on generators and async functions across crate boundaries
|
||||
// and is used to provide better error messages
|
||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
|
||||
pub struct GeneratorDiagnosticData<'tcx> {
|
||||
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||
pub hir_owner: DefId,
|
||||
pub nodes_types: ItemLocalMap<Ty<'tcx>>,
|
||||
pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeckResults<'tcx> {
|
||||
pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
|
||||
TypeckResults {
|
||||
hir_owner,
|
||||
type_dependent_defs: Default::default(),
|
||||
field_indices: Default::default(),
|
||||
user_provided_types: Default::default(),
|
||||
user_provided_sigs: Default::default(),
|
||||
node_types: Default::default(),
|
||||
node_substs: Default::default(),
|
||||
adjustments: Default::default(),
|
||||
pat_binding_modes: Default::default(),
|
||||
pat_adjustments: Default::default(),
|
||||
closure_kind_origins: Default::default(),
|
||||
liberated_fn_sigs: Default::default(),
|
||||
fru_field_types: Default::default(),
|
||||
coercion_casts: Default::default(),
|
||||
used_trait_imports: Lrc::new(Default::default()),
|
||||
tainted_by_errors: None,
|
||||
concrete_opaque_types: Default::default(),
|
||||
closure_min_captures: Default::default(),
|
||||
closure_fake_reads: Default::default(),
|
||||
rvalue_scopes: Default::default(),
|
||||
generator_interior_types: ty::Binder::dummy(Default::default()),
|
||||
treat_byte_string_as_slice: Default::default(),
|
||||
closure_size_eval: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
|
||||
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.res,
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
|
||||
.type_dependent_def(id)
|
||||
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_dependent_defs(
|
||||
&self,
|
||||
) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
|
||||
}
|
||||
|
||||
pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
|
||||
}
|
||||
|
||||
pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
|
||||
self.type_dependent_def(id).map(|(_, def_id)| def_id)
|
||||
}
|
||||
|
||||
pub fn type_dependent_defs_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
|
||||
}
|
||||
|
||||
pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
|
||||
}
|
||||
|
||||
pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
|
||||
}
|
||||
|
||||
pub fn field_index(&self, id: hir::HirId) -> usize {
|
||||
self.field_indices().get(id).cloned().expect("no index for a field")
|
||||
}
|
||||
|
||||
pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
|
||||
self.field_indices().get(id).cloned()
|
||||
}
|
||||
|
||||
pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
|
||||
}
|
||||
|
||||
pub fn user_provided_types_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
|
||||
}
|
||||
|
||||
pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
|
||||
}
|
||||
|
||||
pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
|
||||
}
|
||||
|
||||
pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
|
||||
let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
|
||||
vec.iter()
|
||||
.map(|item| {
|
||||
GeneratorInteriorTypeCause {
|
||||
ty: item.ty,
|
||||
span: item.span,
|
||||
scope_span: item.scope_span,
|
||||
yield_span: item.yield_span,
|
||||
expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
GeneratorDiagnosticData {
|
||||
generator_interior_types: generator_interior_type,
|
||||
hir_owner: self.hir_owner.to_def_id(),
|
||||
nodes_types: self.node_types.clone(),
|
||||
adjustments: self.adjustments.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
|
||||
self.node_type_opt(id).unwrap_or_else(|| {
|
||||
bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_types.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
|
||||
}
|
||||
|
||||
pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
|
||||
}
|
||||
|
||||
pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_substs.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
/// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
|
||||
/// doesn't provide type parameter substitutions.
|
||||
///
|
||||
/// [`expr_ty`]: TypeckResults::expr_ty
|
||||
pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
|
||||
self.node_type(pat.hir_id)
|
||||
}
|
||||
|
||||
/// Returns the type of an expression as a monotype.
|
||||
///
|
||||
/// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
|
||||
/// some cases, we insert `Adjustment` annotations such as auto-deref or
|
||||
/// auto-ref. The type returned by this function does not consider such
|
||||
/// adjustments. See `expr_ty_adjusted()` instead.
|
||||
///
|
||||
/// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
|
||||
/// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
|
||||
/// instead of `fn(ty) -> T with T = isize`.
|
||||
pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
|
||||
self.node_type(expr.hir_id)
|
||||
}
|
||||
|
||||
pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
|
||||
self.node_type_opt(expr.hir_id)
|
||||
}
|
||||
|
||||
pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
|
||||
}
|
||||
|
||||
pub fn adjustments_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
|
||||
}
|
||||
|
||||
pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
|
||||
self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
|
||||
}
|
||||
|
||||
/// Returns the type of `expr`, considering any `Adjustment`
|
||||
/// entry recorded for that expression.
|
||||
pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
|
||||
self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
|
||||
}
|
||||
|
||||
pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
|
||||
self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
|
||||
}
|
||||
|
||||
pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
|
||||
// Only paths and method calls/overloaded operators have
|
||||
// entries in type_dependent_defs, ignore the former here.
|
||||
if let hir::ExprKind::Path(_) = expr.kind {
|
||||
return false;
|
||||
}
|
||||
|
||||
matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
|
||||
}
|
||||
|
||||
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
|
||||
self.pat_binding_modes().get(id).copied().or_else(|| {
|
||||
s.delay_span_bug(sp, "missing binding mode");
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
|
||||
}
|
||||
|
||||
pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
|
||||
}
|
||||
|
||||
pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
|
||||
}
|
||||
|
||||
/// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
|
||||
/// by the closure.
|
||||
pub fn closure_min_captures_flattened(
|
||||
&self,
|
||||
closure_def_id: LocalDefId,
|
||||
) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
|
||||
self.closure_min_captures
|
||||
.get(&closure_def_id)
|
||||
.map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
|
||||
}
|
||||
|
||||
pub fn closure_kind_origins_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
|
||||
}
|
||||
|
||||
pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
|
||||
}
|
||||
|
||||
pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
|
||||
}
|
||||
|
||||
pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
|
||||
}
|
||||
|
||||
pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
|
||||
}
|
||||
|
||||
pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
|
||||
self.coercion_casts.contains(&hir_id.local_id)
|
||||
}
|
||||
|
||||
pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
|
||||
self.coercion_casts.insert(id);
|
||||
}
|
||||
|
||||
pub fn coercion_casts(&self) -> &ItemLocalSet {
|
||||
&self.coercion_casts
|
||||
}
|
||||
}
|
||||
|
||||
/// Validate that the given HirId (respectively its `local_id` part) can be
|
||||
/// safely used as a key in the maps of a TypeckResults. For that to be
|
||||
/// the case, the HirId must have the same `owner` as all the other IDs in
|
||||
/// this table (signified by `hir_owner`). Otherwise the HirId
|
||||
/// would be in a different frame of reference and using its `local_id`
|
||||
/// would result in lookup errors, or worse, in silently wrong data being
|
||||
/// stored/returned.
|
||||
#[inline]
|
||||
fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
||||
if hir_id.owner != hir_owner {
|
||||
invalid_hir_id_for_typeck_results(hir_owner, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
||||
ty::tls::with(|tcx| {
|
||||
bug!(
|
||||
"node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
|
||||
tcx.hir().node_to_string(hir_id),
|
||||
hir_id.owner,
|
||||
hir_owner
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
pub struct LocalTableInContext<'a, V> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a ItemLocalMap<V>,
|
||||
}
|
||||
|
||||
impl<'a, V> LocalTableInContext<'a, V> {
|
||||
pub fn contains_key(&self, id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.contains_key(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn get(&self, id: hir::HirId) -> Option<&V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.get(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
|
||||
self.data.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
|
||||
type Output = V;
|
||||
|
||||
fn index(&self, key: hir::HirId) -> &V {
|
||||
self.get(key).expect("LocalTableInContext: key not found")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LocalTableInContextMut<'a, V> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a mut ItemLocalMap<V>,
|
||||
}
|
||||
|
||||
impl<'a, V> LocalTableInContextMut<'a, V> {
|
||||
pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.get_mut(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.entry(id.local_id)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.insert(id.local_id, val)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.remove(&id.local_id)
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
pub struct UserTypeAnnotationIndex {
|
||||
derive [HashStable]
|
||||
DEBUG_FORMAT = "UserType({})",
|
||||
const START_INDEX = 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Mapping of type annotation indices to canonical user type annotations.
|
||||
pub type CanonicalUserTypeAnnotations<'tcx> =
|
||||
IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
|
||||
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct CanonicalUserTypeAnnotation<'tcx> {
|
||||
pub user_ty: Box<CanonicalUserType<'tcx>>,
|
||||
pub span: Span,
|
||||
pub inferred_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
/// Canonicalized user type annotation.
|
||||
pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
|
||||
|
||||
impl<'tcx> CanonicalUserType<'tcx> {
|
||||
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
|
||||
/// i.e., each thing is mapped to a canonical variable with the same index.
|
||||
pub fn is_identity(&self) -> bool {
|
||||
match self.value {
|
||||
UserType::Ty(_) => false,
|
||||
UserType::TypeOf(_, user_substs) => {
|
||||
if user_substs.user_self_ty.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
|
||||
match kind.unpack() {
|
||||
GenericArgKind::Type(ty) => match ty.kind() {
|
||||
ty::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == b.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
GenericArgKind::Lifetime(r) => match *r {
|
||||
ty::ReLateBound(debruijn, br) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == br.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
GenericArgKind::Const(ct) => match ct.kind() {
|
||||
ty::ConstKind::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == b
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A user-given type annotation attached to a constant. These arise
|
||||
/// from constants that are named via paths, like `Foo::<A>::new` and
|
||||
/// so forth.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub enum UserType<'tcx> {
|
||||
Ty(Ty<'tcx>),
|
||||
|
||||
/// The canonical type is the result of `type_of(def_id)` with the
|
||||
/// given substitutions applied.
|
||||
TypeOf(DefId, UserSubsts<'tcx>),
|
||||
}
|
@ -77,3 +77,9 @@ pub struct SymbolAlreadyDefined {
|
||||
pub span: Option<Span>,
|
||||
pub symbol: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(monomorphize_couldnt_dump_mono_stats)]
|
||||
pub struct CouldntDumpMonoStats {
|
||||
pub error: String,
|
||||
}
|
||||
|
@ -95,6 +95,11 @@
|
||||
mod default;
|
||||
mod merging;
|
||||
|
||||
use std::cmp;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_hir::def_id::DefIdSet;
|
||||
@ -104,11 +109,12 @@ use rustc_middle::mir::mono::{CodegenUnit, Linkage};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::SwitchWithOptPath;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
use crate::collector::InliningMap;
|
||||
use crate::collector::{self, MonoItemCollectionMode};
|
||||
use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy};
|
||||
use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownPartitionStrategy};
|
||||
|
||||
pub struct PartitioningCx<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
@ -411,6 +417,15 @@ fn collect_and_partition_mono_items<'tcx>(
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Output monomorphization stats per def_id
|
||||
if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
|
||||
if let Err(err) =
|
||||
dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref())
|
||||
{
|
||||
tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
|
||||
}
|
||||
}
|
||||
|
||||
if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
|
||||
let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
|
||||
|
||||
@ -465,6 +480,67 @@ fn collect_and_partition_mono_items<'tcx>(
|
||||
(tcx.arena.alloc(mono_items), codegen_units)
|
||||
}
|
||||
|
||||
/// Outputs stats about instantation counts and estimated size, per `MonoItem`'s
|
||||
/// def, to a file in the given output directory.
|
||||
fn dump_mono_items_stats<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
codegen_units: &[CodegenUnit<'tcx>],
|
||||
output_directory: &Option<PathBuf>,
|
||||
crate_name: Option<&str>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let output_directory = if let Some(ref directory) = output_directory {
|
||||
fs::create_dir_all(directory)?;
|
||||
directory
|
||||
} else {
|
||||
Path::new(".")
|
||||
};
|
||||
|
||||
let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate"));
|
||||
let output_path = output_directory.join(&filename);
|
||||
let file = File::create(output_path)?;
|
||||
let mut file = BufWriter::new(file);
|
||||
|
||||
// Gather instantiated mono items grouped by def_id
|
||||
let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
|
||||
for cgu in codegen_units {
|
||||
for (&mono_item, _) in cgu.items() {
|
||||
// Avoid variable-sized compiler-generated shims
|
||||
if mono_item.is_user_defined() {
|
||||
items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Output stats sorted by total instantiated size, from heaviest to lightest
|
||||
let mut stats: Vec<_> = items_per_def_id
|
||||
.into_iter()
|
||||
.map(|(def_id, items)| {
|
||||
let instantiation_count = items.len();
|
||||
let size_estimate = items[0].size_estimate(tcx);
|
||||
let total_estimate = instantiation_count * size_estimate;
|
||||
(def_id, instantiation_count, size_estimate, total_estimate)
|
||||
})
|
||||
.collect();
|
||||
stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate));
|
||||
|
||||
if !stats.is_empty() {
|
||||
writeln!(
|
||||
file,
|
||||
"| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
|
||||
)?;
|
||||
writeln!(file, "| --- | ---: | ---: | ---: |")?;
|
||||
for (def_id, instantiation_count, size_estimate, total_estimate) in stats {
|
||||
let item = with_no_trimmed_paths!(tcx.def_path_str(def_id));
|
||||
writeln!(
|
||||
file,
|
||||
"| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |"
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSet {
|
||||
let (items, cgus) = tcx.collect_and_partition_mono_items(());
|
||||
let mut visited = DefIdSet::default();
|
||||
|
@ -1294,6 +1294,9 @@ options! {
|
||||
computed `block` spans (one span encompassing a block's terminator and \
|
||||
all statements). If `-Z instrument-coverage` is also enabled, create \
|
||||
an additional `.html` file showing the computed coverage spans."),
|
||||
dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
|
||||
parse_switch_with_opt_path, [UNTRACKED],
|
||||
"output statistics about monomorphization collection (format: markdown)"),
|
||||
dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
|
||||
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
|
||||
dylib_lto: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -259,6 +259,10 @@ impl RealFileName {
|
||||
FileNameDisplayPreference::Remapped => {
|
||||
self.remapped_path_if_available().to_string_lossy()
|
||||
}
|
||||
FileNameDisplayPreference::Short => self
|
||||
.local_path_if_available()
|
||||
.file_name()
|
||||
.map_or_else(|| "".into(), |f| f.to_string_lossy()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -302,6 +306,9 @@ pub enum FileNameDisplayPreference {
|
||||
/// Display the path before the application of rewrite rules provided via `--remap-path-prefix`.
|
||||
/// This is appropriate for use in user-facing output (such as diagnostics).
|
||||
Local,
|
||||
/// Display only the filename, as a way to reduce the verbosity of the output.
|
||||
/// This is appropriate for use in user-facing output (such as diagnostics).
|
||||
Short,
|
||||
}
|
||||
|
||||
pub struct FileNameDisplay<'a> {
|
||||
|
@ -438,7 +438,11 @@ impl SourceMap {
|
||||
}
|
||||
}
|
||||
|
||||
fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPreference) -> String {
|
||||
pub fn span_to_string(
|
||||
&self,
|
||||
sp: Span,
|
||||
filename_display_pref: FileNameDisplayPreference,
|
||||
) -> String {
|
||||
if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
|
||||
return "no-location".to_string();
|
||||
}
|
||||
@ -446,12 +450,15 @@ impl SourceMap {
|
||||
let lo = self.lookup_char_pos(sp.lo());
|
||||
let hi = self.lookup_char_pos(sp.hi());
|
||||
format!(
|
||||
"{}:{}:{}: {}:{}",
|
||||
"{}:{}:{}{}",
|
||||
lo.file.name.display(filename_display_pref),
|
||||
lo.line,
|
||||
lo.col.to_usize() + 1,
|
||||
hi.line,
|
||||
hi.col.to_usize() + 1,
|
||||
if let FileNameDisplayPreference::Short = filename_display_pref {
|
||||
String::new()
|
||||
} else {
|
||||
format!(": {}:{}", hi.line, hi.col.to_usize() + 1)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ use rustc_middle::traits::select::OverflowError;
|
||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::error::ExpectedFound;
|
||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::print::{FmtPrinter, Print};
|
||||
use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
|
||||
use rustc_middle::ty::{
|
||||
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
|
||||
TypeVisitable,
|
||||
@ -1757,21 +1757,26 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
let trait_def_id = pred.projection_ty.trait_def_id(self.tcx);
|
||||
let self_ty = pred.projection_ty.self_ty();
|
||||
|
||||
if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
|
||||
Some(format!(
|
||||
"expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it returns `{normalized_ty}`",
|
||||
fn_kind = self_ty.prefix_string(self.tcx)
|
||||
))
|
||||
} else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
|
||||
Some(format!(
|
||||
"expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it resolves to `{normalized_ty}`"
|
||||
))
|
||||
} else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
|
||||
Some(format!(
|
||||
"expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it yields `{normalized_ty}`"
|
||||
))
|
||||
} else {
|
||||
None
|
||||
with_forced_trimmed_paths! {
|
||||
if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
|
||||
Some(format!(
|
||||
"expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it \
|
||||
returns `{normalized_ty}`",
|
||||
fn_kind = self_ty.prefix_string(self.tcx)
|
||||
))
|
||||
} else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
|
||||
Some(format!(
|
||||
"expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
|
||||
resolves to `{normalized_ty}`"
|
||||
))
|
||||
} else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
|
||||
Some(format!(
|
||||
"expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
|
||||
yields `{normalized_ty}`"
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,6 +352,14 @@ pub trait TypeErrCtxtExt<'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
err: &mut Diagnostic,
|
||||
);
|
||||
fn probe_assoc_types_at_expr(
|
||||
&self,
|
||||
type_diffs: &[TypeError<'tcx>],
|
||||
span: Span,
|
||||
prev_ty: Ty<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;
|
||||
}
|
||||
|
||||
fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
|
||||
@ -1618,7 +1626,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
let trait_obj = if has_dyn { &snippet[4..] } else { &snippet };
|
||||
if only_never_return {
|
||||
// No return paths, probably using `panic!()` or similar.
|
||||
// Suggest `-> T`, `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
|
||||
// Suggest `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
|
||||
suggest_trait_object_return_type_alternatives(
|
||||
err,
|
||||
ret_ty.span,
|
||||
@ -2540,6 +2548,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
ObligationCauseCode::SizedArgumentType(sp) => {
|
||||
if let Some(span) = sp {
|
||||
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
|
||||
&& let ty::Clause::Trait(trait_pred) = clause
|
||||
&& let ty::Dynamic(..) = trait_pred.self_ty().kind()
|
||||
{
|
||||
let span = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||
&& snippet.starts_with("dyn ")
|
||||
{
|
||||
let pos = snippet.len() - snippet[3..].trim_start().len();
|
||||
span.with_hi(span.lo() + BytePos(pos as u32))
|
||||
} else {
|
||||
span.shrink_to_lo()
|
||||
};
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"you can use `impl Trait` as the argument type",
|
||||
"impl ".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_lo(),
|
||||
"function arguments must have a statically known size, borrowed types \
|
||||
@ -3152,23 +3179,37 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
|
||||
&& let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
|
||||
&& let Some(pred) = predicates.predicates.get(*idx)
|
||||
&& let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
|
||||
{
|
||||
if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
|
||||
_ => Err(()),
|
||||
})
|
||||
{
|
||||
let mut c = CollectAllMismatches {
|
||||
infcx: self.infcx,
|
||||
param_env,
|
||||
errors: vec![],
|
||||
};
|
||||
if let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
|
||||
_ => Err(()),
|
||||
}) {
|
||||
&& let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
|
||||
_ => Err(()),
|
||||
})
|
||||
{
|
||||
let mut c = CollectAllMismatches {
|
||||
infcx: self.infcx,
|
||||
param_env,
|
||||
errors: vec![],
|
||||
};
|
||||
if let Ok(_) = c.relate(trait_pred, trait_predicate) {
|
||||
type_diffs = c.errors;
|
||||
}
|
||||
} else if let ty::PredicateKind::Clause(
|
||||
ty::Clause::Projection(proj)
|
||||
) = pred.kind().skip_binder()
|
||||
&& let ty::PredicateKind::Clause(
|
||||
ty::Clause::Projection(projection)
|
||||
) = predicate.kind().skip_binder()
|
||||
{
|
||||
type_diffs = vec![
|
||||
Sorts(ty::error::ExpectedFound {
|
||||
expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)),
|
||||
found: projection.term.ty().unwrap(),
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
|
||||
@ -3221,10 +3262,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
|
||||
let tcx = self.tcx;
|
||||
|
||||
let mut print_root_expr = true;
|
||||
let mut assocs = vec![];
|
||||
// We still want to point at the different methods even if there hasn't
|
||||
// been a change of assoc type.
|
||||
let mut call_spans = vec![];
|
||||
let mut expr = expr;
|
||||
let mut prev_ty = self.resolve_vars_if_possible(
|
||||
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
|
||||
@ -3234,63 +3273,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
// vec![1, 2, 3].iter().map(mapper).sum<i32>()
|
||||
// ^^^^^^ ^^^^^^^^^^^
|
||||
expr = rcvr_expr;
|
||||
let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
|
||||
call_spans.push(span);
|
||||
|
||||
let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
|
||||
for diff in &type_diffs {
|
||||
let Sorts(expected_found) = diff else { continue; };
|
||||
let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else { continue; };
|
||||
|
||||
let origin =
|
||||
TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
|
||||
let trait_def_id = proj.trait_def_id(self.tcx);
|
||||
// Make `Self` be equivalent to the type of the call chain
|
||||
// expression we're looking at now, so that we can tell what
|
||||
// for example `Iterator::Item` is at this point in the chain.
|
||||
let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Type { .. } => {
|
||||
if param.index == 0 {
|
||||
return prev_ty.into();
|
||||
}
|
||||
}
|
||||
ty::GenericParamDefKind::Lifetime
|
||||
| ty::GenericParamDefKind::Const { .. } => {}
|
||||
}
|
||||
self.var_for_def(span, param)
|
||||
});
|
||||
// This will hold the resolved type of the associated type, if the
|
||||
// current expression implements the trait that associated type is
|
||||
// in. For example, this would be what `Iterator::Item` is here.
|
||||
let ty_var = self.infcx.next_ty_var(origin);
|
||||
// This corresponds to `<ExprTy as Iterator>::Item = _`.
|
||||
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
|
||||
ty::Clause::Projection(ty::ProjectionPredicate {
|
||||
projection_ty: tcx.mk_alias_ty(proj.def_id, substs),
|
||||
term: ty_var.into(),
|
||||
}),
|
||||
));
|
||||
// Add `<ExprTy as Iterator>::Item = _` obligation.
|
||||
ocx.register_obligation(Obligation::misc(
|
||||
self.tcx,
|
||||
span,
|
||||
expr.hir_id,
|
||||
param_env,
|
||||
projection,
|
||||
));
|
||||
if ocx.select_where_possible().is_empty() {
|
||||
// `ty_var` now holds the type that `Item` is for `ExprTy`.
|
||||
let ty_var = self.resolve_vars_if_possible(ty_var);
|
||||
assocs_in_this_method.push(Some((span, (proj.def_id, ty_var))));
|
||||
} else {
|
||||
// `<ExprTy as Iterator>` didn't select, so likely we've
|
||||
// reached the end of the iterator chain, like the originating
|
||||
// `Vec<_>`.
|
||||
// Keep the space consistent for later zipping.
|
||||
assocs_in_this_method.push(None);
|
||||
}
|
||||
}
|
||||
let assocs_in_this_method =
|
||||
self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
|
||||
assocs.push(assocs_in_this_method);
|
||||
prev_ty = self.resolve_vars_if_possible(
|
||||
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
|
||||
@ -3300,17 +3284,32 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
&& let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
|
||||
&& let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
|
||||
&& let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
|
||||
&& let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
|
||||
&& let Some(binding_expr) = local.init
|
||||
&& let Some(parent) = self.tcx.hir().find(parent_hir_id)
|
||||
{
|
||||
// We've reached the root of the method call chain and it is a
|
||||
// binding. Get the binding creation and try to continue the chain.
|
||||
expr = binding_expr;
|
||||
// We've reached the root of the method call chain...
|
||||
if let hir::Node::Local(local) = parent
|
||||
&& let Some(binding_expr) = local.init
|
||||
{
|
||||
// ...and it is a binding. Get the binding creation and continue the chain.
|
||||
expr = binding_expr;
|
||||
}
|
||||
if let hir::Node::Param(param) = parent {
|
||||
// ...and it is a an fn argument.
|
||||
let prev_ty = self.resolve_vars_if_possible(
|
||||
typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error()),
|
||||
);
|
||||
let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env);
|
||||
if assocs_in_this_method.iter().any(|a| a.is_some()) {
|
||||
assocs.push(assocs_in_this_method);
|
||||
print_root_expr = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// We want the type before deref coercions, otherwise we talk about `&[_]`
|
||||
// instead of `Vec<_>`.
|
||||
if let Some(ty) = typeck_results.expr_ty_opt(expr) {
|
||||
if let Some(ty) = typeck_results.expr_ty_opt(expr) && print_root_expr {
|
||||
let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
|
||||
// Point at the root expression
|
||||
// vec![1, 2, 3].iter().map(mapper).sum<i32>()
|
||||
@ -3324,7 +3323,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
let Some(prev_assoc_in_method) = assocs.peek() else {
|
||||
for entry in assocs_in_method {
|
||||
let Some((span, (assoc, ty))) = entry else { continue; };
|
||||
if type_diffs.iter().any(|diff| {
|
||||
if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
|
||||
let Sorts(expected_found) = diff else { return false; };
|
||||
self.can_eq(param_env, expected_found.found, ty).is_ok()
|
||||
}) {
|
||||
@ -3353,7 +3352,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
|
||||
|
||||
let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
|
||||
if ty != *prev_ty {
|
||||
if self.can_eq(param_env, ty, *prev_ty).is_err() {
|
||||
if type_diffs.iter().any(|diff| {
|
||||
let Sorts(expected_found) = diff else { return false; };
|
||||
self.can_eq(param_env, expected_found.found, ty).is_ok()
|
||||
@ -3380,13 +3379,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
for span in call_spans {
|
||||
if span_labels.iter().find(|(s, _)| *s == span).is_none() {
|
||||
// Ensure we are showing the entire chain, even if the assoc types
|
||||
// haven't changed.
|
||||
span_labels.push((span, String::new()));
|
||||
}
|
||||
}
|
||||
if !primary_spans.is_empty() {
|
||||
let mut multi_span: MultiSpan = primary_spans.into();
|
||||
for (span, label) in span_labels {
|
||||
@ -3394,13 +3386,70 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
err.span_note(
|
||||
multi_span,
|
||||
format!(
|
||||
"the method call chain might not have had the expected \
|
||||
associated types",
|
||||
),
|
||||
format!("the method call chain might not have had the expected associated types"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn probe_assoc_types_at_expr(
|
||||
&self,
|
||||
type_diffs: &[TypeError<'tcx>],
|
||||
span: Span,
|
||||
prev_ty: Ty<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
|
||||
let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
|
||||
let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
|
||||
for diff in type_diffs {
|
||||
let Sorts(expected_found) = diff else { continue; };
|
||||
let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else { continue; };
|
||||
|
||||
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
|
||||
let trait_def_id = proj.trait_def_id(self.tcx);
|
||||
// Make `Self` be equivalent to the type of the call chain
|
||||
// expression we're looking at now, so that we can tell what
|
||||
// for example `Iterator::Item` is at this point in the chain.
|
||||
let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Type { .. } => {
|
||||
if param.index == 0 {
|
||||
return prev_ty.into();
|
||||
}
|
||||
}
|
||||
ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Const { .. } => {}
|
||||
}
|
||||
self.var_for_def(span, param)
|
||||
});
|
||||
// This will hold the resolved type of the associated type, if the
|
||||
// current expression implements the trait that associated type is
|
||||
// in. For example, this would be what `Iterator::Item` is here.
|
||||
let ty_var = self.infcx.next_ty_var(origin);
|
||||
// This corresponds to `<ExprTy as Iterator>::Item = _`.
|
||||
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: self.tcx.mk_alias_ty(proj.def_id, substs),
|
||||
term: ty_var.into(),
|
||||
},
|
||||
)));
|
||||
// Add `<ExprTy as Iterator>::Item = _` obligation.
|
||||
ocx.register_obligation(Obligation::misc(
|
||||
self.tcx, span, body_id, param_env, projection,
|
||||
));
|
||||
if ocx.select_where_possible().is_empty() {
|
||||
// `ty_var` now holds the type that `Item` is for `ExprTy`.
|
||||
let ty_var = self.resolve_vars_if_possible(ty_var);
|
||||
assocs_in_this_method.push(Some((span, (proj.def_id, ty_var))));
|
||||
} else {
|
||||
// `<ExprTy as Iterator>` didn't select, so likely we've
|
||||
// reached the end of the iterator chain, like the originating
|
||||
// `Vec<_>`.
|
||||
// Keep the space consistent for later zipping.
|
||||
assocs_in_this_method.push(None);
|
||||
}
|
||||
}
|
||||
assocs_in_this_method
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a hint to add a missing borrow or remove an unnecessary one.
|
||||
@ -3580,13 +3629,6 @@ fn suggest_trait_object_return_type_alternatives(
|
||||
trait_obj: &str,
|
||||
is_object_safe: bool,
|
||||
) {
|
||||
err.span_suggestion(
|
||||
ret_ty,
|
||||
"use some type `T` that is `T: Sized` as the return type if all return paths have the \
|
||||
same type",
|
||||
"T",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.span_suggestion(
|
||||
ret_ty,
|
||||
&format!(
|
||||
|
@ -451,19 +451,21 @@ impl<'tcx> WfPredicates<'tcx> {
|
||||
GenericArgKind::Const(ct) => {
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(uv) => {
|
||||
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
|
||||
self.out.extend(obligations);
|
||||
if !ct.has_escaping_bound_vars() {
|
||||
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
|
||||
self.out.extend(obligations);
|
||||
|
||||
let predicate =
|
||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
|
||||
let cause = self.cause(traits::WellFormed(None));
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
self.tcx(),
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
predicate,
|
||||
));
|
||||
let predicate =
|
||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
|
||||
let cause = self.cause(traits::WellFormed(None));
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
self.tcx(),
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
predicate,
|
||||
));
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Infer(_) => {
|
||||
let cause = self.cause(traits::WellFormed(None));
|
||||
|
@ -325,7 +325,7 @@ pub(crate) fn build_impls(
|
||||
// * https://github.com/rust-lang/rust/pull/99917 — where the feature got used
|
||||
// * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error
|
||||
if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
|
||||
use rustc_middle::ty::fast_reject::SimplifiedTypeGen::*;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType::*;
|
||||
let type_ =
|
||||
if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) };
|
||||
for &did in tcx.incoherent_impls(type_) {
|
||||
|
@ -1870,7 +1870,7 @@ impl PrimitiveType {
|
||||
}
|
||||
|
||||
pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
|
||||
use ty::fast_reject::SimplifiedTypeGen::*;
|
||||
use ty::fast_reject::SimplifiedType::*;
|
||||
use ty::{FloatTy, IntTy, UintTy};
|
||||
use PrimitiveType::*;
|
||||
static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
|
||||
|
@ -1071,6 +1071,10 @@ pre.rust .doccomment {
|
||||
color: var(--code-highlight-doc-comment-color);
|
||||
}
|
||||
|
||||
.rustdoc.source .example-wrap pre.rust a {
|
||||
background: var(--codeblock-link-background);
|
||||
}
|
||||
|
||||
.example-wrap.compile_fail,
|
||||
.example-wrap.should_panic {
|
||||
border-left: 2px solid var(--codeblock-error-color);
|
||||
|
@ -88,6 +88,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
||||
--source-sidebar-background-selected: #14191f;
|
||||
--source-sidebar-background-hover: #14191f;
|
||||
--table-alt-row-background-color: #191f26;
|
||||
--codeblock-link-background: #333;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
@ -154,9 +155,6 @@ pre, .rustdoc.source .example-wrap {
|
||||
.sidebar h3 a {
|
||||
color: white;
|
||||
}
|
||||
body.source .example-wrap pre.rust a {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.result-name .primitive > i, .result-name .keyword > i {
|
||||
color: #788797;
|
||||
|
@ -83,10 +83,7 @@
|
||||
--source-sidebar-background-selected: #333;
|
||||
--source-sidebar-background-hover: #444;
|
||||
--table-alt-row-background-color: #2A2A2A;
|
||||
}
|
||||
|
||||
body.source .example-wrap pre.rust a {
|
||||
background: #333;
|
||||
--codeblock-link-background: #333;
|
||||
}
|
||||
|
||||
#titles > button:not(.selected) {
|
||||
|
@ -80,10 +80,7 @@
|
||||
--source-sidebar-background-selected: #fff;
|
||||
--source-sidebar-background-hover: #e0e0e0;
|
||||
--table-alt-row-background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
body.source .example-wrap pre.rust a {
|
||||
background: #eee;
|
||||
--codeblock-link-background: #eee;
|
||||
}
|
||||
|
||||
#titles > button:not(.selected) {
|
||||
|
@ -35,6 +35,7 @@
|
||||
-Z dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
|
||||
-Z dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
|
||||
-Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
|
||||
-Z dump-mono-stats=val -- output statistics about monomorphization collection (format: markdown)
|
||||
-Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
|
||||
-Z dylib-lto=val -- enables LTO for dylib crate type
|
||||
-Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
|
||||
|
@ -4,5 +4,5 @@ trait I32Iterator = Iterator<Item = i32>;
|
||||
|
||||
fn main() {
|
||||
let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||
//~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
//~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
--> $DIR/associated-types-overridden-binding-2.rs:6:43
|
||||
|
|
||||
LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
|
||||
error[E0599]: no method named `closure` found for reference `&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
|
||||
--> $DIR/issue-33784.rs:27:7
|
||||
|
|
||||
LL | p.closure();
|
||||
@ -9,7 +9,7 @@ help: to call the function stored in `closure`, surround the field access with p
|
||||
LL | (p.closure)();
|
||||
| + +
|
||||
|
||||
error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
|
||||
error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
|
||||
--> $DIR/issue-33784.rs:29:7
|
||||
|
|
||||
LL | q.fn_ptr();
|
||||
|
14
src/test/ui/const-generics/issue-105689.rs
Normal file
14
src/test/ui/const-generics/issue-105689.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// check-pass
|
||||
// edition:2021
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#[allow(unused)]
|
||||
async fn foo<'a>() {
|
||||
let _data = &mut [0u8; { 1 + 4 }];
|
||||
bar().await
|
||||
}
|
||||
|
||||
async fn bar() {}
|
||||
|
||||
fn main() {}
|
@ -100,22 +100,22 @@ help: a unit struct with a similar name exists
|
||||
LL | let xe1 = XEmpty2();
|
||||
| ~~~~~~~
|
||||
|
||||
error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
|
||||
error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
|
||||
--> $DIR/empty-struct-braces-expr.rs:25:19
|
||||
|
|
||||
LL | let xe3 = XE::Empty3;
|
||||
| ^^^^^^
|
||||
| |
|
||||
| variant or associated item not found in `empty_struct::XE`
|
||||
| variant or associated item not found in `XE`
|
||||
| help: there is a variant with a similar name: `XEmpty3`
|
||||
|
||||
error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
|
||||
error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
|
||||
--> $DIR/empty-struct-braces-expr.rs:26:19
|
||||
|
|
||||
LL | let xe3 = XE::Empty3();
|
||||
| ^^^^^^
|
||||
| |
|
||||
| variant or associated item not found in `empty_struct::XE`
|
||||
| variant or associated item not found in `XE`
|
||||
| help: there is a variant with a similar name: `XEmpty3`
|
||||
|
||||
error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE`
|
||||
|
@ -1,5 +1,5 @@
|
||||
#![allow(unused, bare_trait_objects)]
|
||||
#[repr(align(256))]
|
||||
#[allow(dead_code)]
|
||||
struct A {
|
||||
v: u8,
|
||||
}
|
||||
@ -14,13 +14,17 @@ impl Foo for A {
|
||||
}
|
||||
}
|
||||
|
||||
fn foo(x: dyn Foo) {
|
||||
//~^ ERROR [E0277]
|
||||
fn foo(x: dyn Foo) { //~ ERROR [E0277]
|
||||
x.foo()
|
||||
}
|
||||
|
||||
fn bar(x: Foo) { //~ ERROR [E0277]
|
||||
x.foo()
|
||||
}
|
||||
|
||||
fn qux(_: [()]) {} //~ ERROR [E0277]
|
||||
|
||||
fn main() {
|
||||
let x: Box<dyn Foo> = Box::new(A { v: 22 });
|
||||
foo(*x);
|
||||
//~^ ERROR [E0277]
|
||||
foo(*x); //~ ERROR [E0277]
|
||||
}
|
||||
|
@ -6,13 +6,47 @@ LL | fn foo(x: dyn Foo) {
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: you can use `impl Trait` as the argument type
|
||||
|
|
||||
LL | fn foo(x: impl Foo) {
|
||||
| ~~~~
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | fn foo(x: &dyn Foo) {
|
||||
| +
|
||||
|
||||
error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
|
||||
--> $DIR/feature-gate-unsized_fn_params.rs:24:9
|
||||
--> $DIR/feature-gate-unsized_fn_params.rs:21:8
|
||||
|
|
||||
LL | fn bar(x: Foo) {
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: you can use `impl Trait` as the argument type
|
||||
|
|
||||
LL | fn bar(x: impl Foo) {
|
||||
| ++++
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | fn bar(x: &Foo) {
|
||||
| +
|
||||
|
||||
error[E0277]: the size for values of type `[()]` cannot be known at compilation time
|
||||
--> $DIR/feature-gate-unsized_fn_params.rs:25:8
|
||||
|
|
||||
LL | fn qux(_: [()]) {}
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `[()]`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | fn qux(_: &[()]) {}
|
||||
| +
|
||||
|
||||
error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
|
||||
--> $DIR/feature-gate-unsized_fn_params.rs:29:9
|
||||
|
|
||||
LL | foo(*x);
|
||||
| ^^ doesn't have a size known at compile-time
|
||||
@ -21,6 +55,6 @@ LL | foo(*x);
|
||||
= note: all function arguments must have a statically known size
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -6,6 +6,10 @@ LL | fn f(f: dyn FnOnce()) {}
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `(dyn FnOnce() + 'static)`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: you can use `impl Trait` as the argument type
|
||||
|
|
||||
LL | fn f(f: impl FnOnce()) {}
|
||||
| ~~~~
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | fn f(f: &dyn FnOnce()) {}
|
||||
|
@ -17,11 +17,11 @@ note: `Bar` defines an item `bar`, perhaps you need to implement it
|
||||
LL | trait Bar {
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `bar` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>` in the current scope
|
||||
error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:22:36]>` in the current scope
|
||||
--> $DIR/fn-help-with-err.rs:23:10
|
||||
|
|
||||
LL | arc2.bar();
|
||||
| ^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>`
|
||||
| ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:22:36]>`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `Bar` defines an item `bar`, perhaps you need to implement it
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>`, but its trait bounds were not satisfied
|
||||
error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@issue-30786.rs:117:27]>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-30786.rs:118:22
|
||||
|
|
||||
LL | pub struct Map<S, F> {
|
||||
@ -8,7 +8,7 @@ LL | pub struct Map<S, F> {
|
||||
| doesn't satisfy `_: StreamExt`
|
||||
...
|
||||
LL | let filter = map.filterx(|x: &_| true);
|
||||
| ^^^^^^^ method cannot be called due to unsatisfied trait bounds
|
||||
| ^^^^^^^ method cannot be called on `Map<Repeat, [closure@issue-30786.rs:117:27]>` due to unsatisfied trait bounds
|
||||
|
|
||||
note: the following trait bounds were not satisfied:
|
||||
`&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
|
||||
@ -19,7 +19,7 @@ note: the following trait bounds were not satisfied:
|
||||
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
||||
| --------- - ^^^^^^ unsatisfied trait bound introduced here
|
||||
|
||||
error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied
|
||||
error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-30786.rs:130:24
|
||||
|
|
||||
LL | pub struct Filter<S, F> {
|
||||
|
@ -30,7 +30,7 @@ LL | where
|
||||
LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
|
||||
|
||||
error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]` to be a closure that returns `Unit3`, but it returns `Unit4`
|
||||
error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4`
|
||||
--> $DIR/issue-62203-hrtb-ice.rs:39:9
|
||||
|
|
||||
LL | let v = Unit2.m(
|
||||
|
@ -70,10 +70,6 @@ error[E0746]: return type cannot have an unboxed trait object
|
||||
LL | fn bak() -> dyn Trait { unimplemented!() }
|
||||
| ^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
|
||||
|
|
||||
LL | fn bak() -> T { unimplemented!() }
|
||||
| ~
|
||||
help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature
|
||||
|
|
||||
LL | fn bak() -> impl Trait { unimplemented!() }
|
||||
|
@ -145,11 +145,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
|
||||
LL | pub trait Bar {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
|
||||
error[E0599]: no method named `method2` found for struct `Foo` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:50:37
|
||||
|
|
||||
LL | no_method_suggested_traits::Foo.method2();
|
||||
| ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
|
||||
| ^^^^^^^ method not found in `Foo`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
|
||||
@ -158,11 +158,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
|
||||
LL | pub trait Bar {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
|
||||
error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Foo>>` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:52:71
|
||||
|
|
||||
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
|
||||
| ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
|
||||
| ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
|
||||
@ -171,11 +171,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
|
||||
LL | pub trait Bar {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
|
||||
error[E0599]: no method named `method2` found for enum `Bar` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:54:40
|
||||
|
|
||||
LL | no_method_suggested_traits::Bar::X.method2();
|
||||
| ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
|
||||
| ^^^^^^^ method not found in `Bar`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
|
||||
@ -184,11 +184,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
|
||||
LL | pub trait Bar {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
|
||||
error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Bar>>` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:56:74
|
||||
|
|
||||
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
|
||||
| ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
|
||||
| ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
|
||||
@ -255,29 +255,29 @@ error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&usize>>`
|
||||
LL | std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
|
||||
| ^^^^^^^ method not found in `Rc<&mut Box<&usize>>`
|
||||
|
||||
error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
|
||||
error[E0599]: no method named `method3` found for struct `Foo` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:71:37
|
||||
|
|
||||
LL | no_method_suggested_traits::Foo.method3();
|
||||
| ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
|
||||
| ^^^^^^^ method not found in `Foo`
|
||||
|
||||
error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
|
||||
error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:72:71
|
||||
|
|
||||
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
|
||||
| ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
|
||||
| ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
|
||||
|
||||
error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
|
||||
error[E0599]: no method named `method3` found for enum `Bar` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:74:40
|
||||
|
|
||||
LL | no_method_suggested_traits::Bar::X.method3();
|
||||
| ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
|
||||
| ^^^^^^^ method not found in `Bar`
|
||||
|
||||
error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
|
||||
error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope
|
||||
--> $DIR/no-method-suggested-traits.rs:75:74
|
||||
|
|
||||
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
|
||||
| ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
|
||||
| ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
|
||||
|
@ -4,10 +4,6 @@ error[E0746]: return type cannot have an unboxed trait object
|
||||
LL | dyn AbstractRenderer
|
||||
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
|
||||
|
|
||||
LL | T
|
||||
|
|
||||
help: use `impl AbstractRenderer` as the return type if all return paths have the same type but you want to expose only the trait in the signature
|
||||
|
|
||||
LL | impl AbstractRenderer
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
|
||||
error[E0599]: no function or associated item named `new_undirected` found for struct `Graph<i32, i32>` in the current scope
|
||||
--> $DIR/issue-30123.rs:7:33
|
||||
|
|
||||
LL | let ug = Graph::<i32, i32>::new_undirected();
|
||||
| ^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph<i32, i32>`
|
||||
| ^^^^^^^^^^^^^^ function or associated item not found in `Graph<i32, i32>`
|
||||
|
|
||||
= note: the function or associated item was found for
|
||||
- `issue_30123_aux::Graph<N, E, Undirected>`
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>` to be an iterator that yields `&_`, but it yields `u8`
|
||||
error[E0271]: expected `TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>` to be an iterator that yields `&_`, but it yields `u8`
|
||||
--> $DIR/issue-31173.rs:11:10
|
||||
|
|
||||
LL | .cloned()
|
||||
@ -6,10 +6,22 @@ LL | .cloned()
|
||||
|
|
||||
= note: expected reference `&_`
|
||||
found type `u8`
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/issue-31173.rs:3:20
|
||||
|
|
||||
LL | pub fn get_tok(it: &mut IntoIter<u8>) {
|
||||
| ^^^^^^^^^^^^^^^^^ `Iterator::Item` is `u8` here
|
||||
...
|
||||
LL | .take_while(|&x| {
|
||||
| __________-
|
||||
LL | | found_e = true;
|
||||
LL | | false
|
||||
LL | | })
|
||||
| |__________- `Iterator::Item` remains `u8` here
|
||||
note: required by a bound in `cloned`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>`, but its trait bounds were not satisfied
|
||||
error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-31173.rs:12:10
|
||||
|
|
||||
LL | .collect();
|
||||
|
@ -3,7 +3,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
//~^ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
//~| ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
//~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
//~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
--> $DIR/issue-33941.rs:6:36
|
||||
|
|
||||
LL | for _ in HashMap::new().iter().cloned() {}
|
||||
@ -6,10 +6,17 @@ LL | for _ in HashMap::new().iter().cloned() {}
|
||||
|
|
||||
= note: expected reference `&_`
|
||||
found tuple `(&_, &_)`
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/issue-33941.rs:6:29
|
||||
|
|
||||
LL | for _ in HashMap::new().iter().cloned() {}
|
||||
| -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here
|
||||
| |
|
||||
| this expression has type `HashMap<_, _>`
|
||||
note: required by a bound in `cloned`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
--> $DIR/issue-33941.rs:6:14
|
||||
|
|
||||
LL | for _ in HashMap::new().iter().cloned() {}
|
||||
@ -20,7 +27,7 @@ LL | for _ in HashMap::new().iter().cloned() {}
|
||||
= note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
|
||||
= note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator`
|
||||
|
||||
error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
--> $DIR/issue-33941.rs:6:14
|
||||
|
|
||||
LL | for _ in HashMap::new().iter().cloned() {}
|
||||
|
@ -5,7 +5,7 @@ LL | pub struct Iterate<T, F> {
|
||||
| ------------------------ method `iter` not found for this struct
|
||||
...
|
||||
LL | println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
|
||||
| ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:27]>`
|
||||
| ^^^^ method not found in `Iterate<{integer}, [closure@issue-41880.rs:26:24]>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -23,6 +23,10 @@ LL | pub fn f(_: dyn ToString) {}
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `(dyn ToString + 'static)`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: you can use `impl Trait` as the argument type
|
||||
|
|
||||
LL | pub fn f(_: impl ToString) {}
|
||||
| ~~~~
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | pub fn f(_: &dyn ToString) {}
|
||||
|
@ -6,6 +6,10 @@ LL | r: dyn A + 'static
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `(dyn A + 'static)`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: you can use `impl Trait` as the argument type
|
||||
|
|
||||
LL | r: impl A + 'static
|
||||
| ~~~~
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | r: &dyn A + 'static
|
||||
|
@ -1,3 +1,11 @@
|
||||
use std::collections::hash_set::Iter;
|
||||
use std::collections::HashSet;
|
||||
|
||||
fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
|
||||
let i = i.map(|x| x.clone());
|
||||
i.collect() //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let scores = vec![(0, 0)]
|
||||
.iter()
|
||||
@ -38,4 +46,8 @@ fn main() {
|
||||
});
|
||||
let f = e.filter(|_| false);
|
||||
let g: Vec<i32> = f.collect(); //~ ERROR E0277
|
||||
|
||||
let mut s = HashSet::new();
|
||||
s.insert(1u8);
|
||||
println!("{:?}", iter_to_vec(s.iter()));
|
||||
}
|
||||
|
@ -1,5 +1,23 @@
|
||||
error[E0277]: a value of type `Vec<X>` cannot be built from an iterator over elements of type `&X`
|
||||
--> $DIR/invalid-iterator-chain.rs:6:7
|
||||
|
|
||||
LL | i.collect()
|
||||
| ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
|
||||
|
|
||||
= help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
|
||||
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/invalid-iterator-chain.rs:4:26
|
||||
|
|
||||
LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
|
||||
| ^^^^^^^^^^^ `Iterator::Item` is `&X` here
|
||||
LL | let i = i.map(|x| x.clone());
|
||||
| ------------------ `Iterator::Item` remains `&X` here
|
||||
note: required by a bound in `collect`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
|
||||
--> $DIR/invalid-iterator-chain.rs:7:27
|
||||
--> $DIR/invalid-iterator-chain.rs:15:27
|
||||
|
|
||||
LL | println!("{}", scores.sum::<i32>());
|
||||
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
|
||||
@ -9,7 +27,7 @@ LL | println!("{}", scores.sum::<i32>());
|
||||
<i32 as Sum<&'a i32>>
|
||||
<i32 as Sum>
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/invalid-iterator-chain.rs:4:10
|
||||
--> $DIR/invalid-iterator-chain.rs:12:10
|
||||
|
|
||||
LL | let scores = vec![(0, 0)]
|
||||
| ------------ this expression has type `Vec<({integer}, {integer})>`
|
||||
@ -24,7 +42,7 @@ note: required by a bound in `std::iter::Iterator::sum`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
|
||||
--> $DIR/invalid-iterator-chain.rs:18:14
|
||||
--> $DIR/invalid-iterator-chain.rs:26:14
|
||||
|
|
||||
LL | .sum::<i32>(),
|
||||
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
|
||||
@ -34,7 +52,7 @@ LL | .sum::<i32>(),
|
||||
<i32 as Sum<&'a i32>>
|
||||
<i32 as Sum>
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/invalid-iterator-chain.rs:12:14
|
||||
--> $DIR/invalid-iterator-chain.rs:20:14
|
||||
|
|
||||
LL | vec![0, 1]
|
||||
| ---------- this expression has type `Vec<{integer}>`
|
||||
@ -56,7 +74,7 @@ note: required by a bound in `std::iter::Iterator::sum`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64`
|
||||
--> $DIR/invalid-iterator-chain.rs:28:14
|
||||
--> $DIR/invalid-iterator-chain.rs:36:14
|
||||
|
|
||||
LL | .sum::<i32>(),
|
||||
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=f64>`
|
||||
@ -66,7 +84,7 @@ LL | .sum::<i32>(),
|
||||
<i32 as Sum<&'a i32>>
|
||||
<i32 as Sum>
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/invalid-iterator-chain.rs:24:14
|
||||
--> $DIR/invalid-iterator-chain.rs:32:14
|
||||
|
|
||||
LL | vec![0, 1]
|
||||
| ---------- this expression has type `Vec<{integer}>`
|
||||
@ -84,7 +102,7 @@ note: required by a bound in `std::iter::Iterator::sum`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
|
||||
--> $DIR/invalid-iterator-chain.rs:30:54
|
||||
--> $DIR/invalid-iterator-chain.rs:38:54
|
||||
|
|
||||
LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
|
||||
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
|
||||
@ -94,7 +112,7 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
|
||||
<i32 as Sum<&'a i32>>
|
||||
<i32 as Sum>
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/invalid-iterator-chain.rs:30:38
|
||||
--> $DIR/invalid-iterator-chain.rs:38:38
|
||||
|
|
||||
LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
|
||||
| ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
|
||||
@ -105,7 +123,7 @@ note: required by a bound in `std::iter::Iterator::sum`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
|
||||
--> $DIR/invalid-iterator-chain.rs:31:40
|
||||
--> $DIR/invalid-iterator-chain.rs:39:40
|
||||
|
|
||||
LL | println!("{}", vec![(), ()].iter().sum::<i32>());
|
||||
| ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
|
||||
@ -115,7 +133,7 @@ LL | println!("{}", vec![(), ()].iter().sum::<i32>());
|
||||
<i32 as Sum<&'a i32>>
|
||||
<i32 as Sum>
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/invalid-iterator-chain.rs:31:33
|
||||
--> $DIR/invalid-iterator-chain.rs:39:33
|
||||
|
|
||||
LL | println!("{}", vec![(), ()].iter().sum::<i32>());
|
||||
| ------------ ^^^^^^ `Iterator::Item` is `&()` here
|
||||
@ -125,7 +143,7 @@ note: required by a bound in `std::iter::Iterator::sum`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
|
||||
--> $DIR/invalid-iterator-chain.rs:40:25
|
||||
--> $DIR/invalid-iterator-chain.rs:48:25
|
||||
|
|
||||
LL | let g: Vec<i32> = f.collect();
|
||||
| ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
|
||||
@ -133,7 +151,7 @@ LL | let g: Vec<i32> = f.collect();
|
||||
= help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
|
||||
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/invalid-iterator-chain.rs:36:15
|
||||
--> $DIR/invalid-iterator-chain.rs:44:15
|
||||
|
|
||||
LL | let a = vec![0];
|
||||
| ------- this expression has type `Vec<{integer}>`
|
||||
@ -153,6 +171,6 @@ LL | let f = e.filter(|_| false);
|
||||
note: required by a bound in `collect`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -23,7 +23,7 @@ error[E0599]: no method named `extend` found for struct `Map` in the current sco
|
||||
--> $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:21]>`
|
||||
| ^^^^^^ method not found in `Map<Iter<'_, i32>, [closure@method-not-found-generic-arg-elision.rs:87:18]>`
|
||||
|
||||
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
|
||||
|
@ -13,7 +13,7 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
|
||||
note: required by a bound in `filter`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>`, but its trait bounds were not satisfied
|
||||
error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-36053-2.rs:7:55
|
||||
|
|
||||
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0271]: expected `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to be a closure that returns `()`, but it returns `!`
|
||||
error[E0271]: expected `[closure@fallback-closure-wrap.rs:18:40]` to be a closure that returns `()`, but it returns `!`
|
||||
--> $DIR/fallback-closure-wrap.rs:18:31
|
||||
|
|
||||
LL | let error = Closure::wrap(Box::new(move || {
|
||||
|
@ -6,6 +6,10 @@ LL | fn foo(_x: K) {}
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `(dyn I + 'static)`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: you can use `impl Trait` as the argument type
|
||||
|
|
||||
LL | fn foo(_x: impl K) {}
|
||||
| ++++
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | fn foo(_x: &K) {}
|
||||
|
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
fn wat<T: Clone>(t: &T) -> T {
|
||||
t.clone() //~ ERROR E0308
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Foo;
|
||||
|
||||
fn wut(t: &Foo) -> Foo {
|
||||
t.clone() //~ ERROR E0308
|
||||
}
|
||||
|
||||
fn main() {
|
||||
wat(&42);
|
||||
wut(&Foo);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
// run-rustfix
|
||||
fn wat<T>(t: &T) -> T {
|
||||
t.clone() //~ ERROR E0308
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
||||
fn wut(t: &Foo) -> Foo {
|
||||
t.clone() //~ ERROR E0308
|
||||
}
|
||||
|
||||
fn main() {
|
||||
wat(&42);
|
||||
wut(&Foo);
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
|
||||
|
|
||||
LL | fn wat<T>(t: &T) -> T {
|
||||
| - - expected `T` because of return type
|
||||
| |
|
||||
| this type parameter
|
||||
LL | t.clone()
|
||||
| ^^^^^^^^^ expected type parameter `T`, found `&T`
|
||||
|
|
||||
= note: expected type parameter `T`
|
||||
found reference `&T`
|
||||
note: `T` does not implement `Clone`, so `&T` was cloned instead
|
||||
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
|
||||
|
|
||||
LL | t.clone()
|
||||
| ^
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | fn wat<T: Clone>(t: &T) -> T {
|
||||
| +++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
|
||||
|
|
||||
LL | fn wut(t: &Foo) -> Foo {
|
||||
| --- expected `Foo` because of return type
|
||||
LL | t.clone()
|
||||
| ^^^^^^^^^ expected struct `Foo`, found `&Foo`
|
||||
|
|
||||
note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
|
||||
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
|
||||
|
|
||||
LL | t.clone()
|
||||
| ^
|
||||
help: consider annotating `Foo` with `#[derive(Clone)]`
|
||||
|
|
||||
LL | #[derive(Clone)]
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -20,11 +20,11 @@ LL | let fp = BufWriter::new(fp);
|
||||
note: required by a bound in `BufWriter`
|
||||
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
|
||||
|
||||
error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn std::io::Write>`, but its trait bounds were not satisfied
|
||||
error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied
|
||||
--> $DIR/mut-borrow-needed-by-trait.rs:21:5
|
||||
|
|
||||
LL | writeln!(fp, "hello world").unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn std::io::Write>` due to unsatisfied trait bounds
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
|
||||
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
|
||||
|
|
||||
= note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
|
||||
|
@ -10,7 +10,7 @@ pub trait Foo: Iterator<Item = <Self as Foo>::Key> {
|
||||
|
||||
impl Foo for IntoIter<i32> {
|
||||
type Key = u32;
|
||||
//~^ ERROR expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
|
||||
//~^ ERROR expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0271]: expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
|
||||
error[E0271]: expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
|
||||
--> $DIR/assoc-type-in-superbad.rs:12:16
|
||||
|
|
||||
LL | type Key = u32;
|
||||
|
@ -20,6 +20,10 @@ LL | fn foo(_x: Foo + Send) {
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: you can use `impl Trait` as the argument type
|
||||
|
|
||||
LL | fn foo(_x: impl Foo + Send) {
|
||||
| ++++
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | fn foo(_x: &Foo + Send) {
|
||||
|
@ -8,7 +8,7 @@ trait Foo {
|
||||
|
||||
impl Foo for () {
|
||||
type Bar = std::vec::IntoIter<u32>;
|
||||
//~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
|
||||
//~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
|
||||
}
|
||||
|
||||
fn incoherent() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
|
||||
error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
|
||||
--> $DIR/issue-57961.rs:10:16
|
||||
|
|
||||
LL | type X = impl Sized;
|
||||
|
@ -12,6 +12,10 @@ note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
|
|
||||
LL | nc.clone()
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL | #[derive(Clone)]
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope
|
||||
error[E0599]: no method named `call` found for closure `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` in the current scope
|
||||
--> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
|
||||
|
|
||||
LL | mut_.call((0, ));
|
||||
| ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]`
|
||||
| ^^^^ method not found in `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -97,7 +97,7 @@ use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::ty as rustc_ty;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
||||
use rustc_middle::ty::binding::BindingMode;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedTypeGen::{
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType::{
|
||||
ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType,
|
||||
PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user