diff --git a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl index 48ddb54b79e79..243d10bfa0621 100644 --- a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl +++ b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl @@ -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} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 719f44f9f665a..407d6ac8544c2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -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)]); + } } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 5c0d5f32f0fd0..63cec9216eb89 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -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: &[( diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 15a24aa4ace51..1e8d5f7eae87a 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -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> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 70ac5acb40ead..173c5ed4feef0 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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, -} - -/// 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 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, -} - -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 { - 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 { - 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 of `.await` or `yield` expression. - pub yield_span: Span, - /// Expr which the type evaluated from. - pub expr: Option, -} - -// 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>>, - pub hir_owner: DefId, - pub nodes_types: ItemLocalMap>, - pub adjustments: ItemLocalMap>>, -} - -#[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 `::X` associated paths and - /// method calls, including those of overloaded operators. - type_dependent_defs: ItemLocalMap>, - - /// 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, - - /// 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>, - - /// 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>, - - /// 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::>()`, then the - /// canonical substitutions would include only `for { Vec }`. - /// - /// See also `AscribeUserType` statement in MIR. - user_provided_types: ItemLocalMap>, - - /// Stores the canonicalized types provided by the user. See also - /// `AscribeUserType` statement in MIR. - pub user_provided_sigs: LocalDefIdMap>, - - adjustments: ItemLocalMap>>, - - /// Stores the actual binding mode for all instances of hir::BindingAnnotation. - pat_binding_modes: ItemLocalMap, - - /// 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, &Option]`. Empty vectors are not stored. - /// - /// See: - /// - pat_adjustments: ItemLocalMap>>, - - /// 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>, - - /// 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>>, - - /// 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>, - - /// If any errors occurred while type-checking this body, - /// this field will be set to `Some(ErrorGuaranteed)`. - pub tainted_by_errors: Option, - - /// 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>, - - /// 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, 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>>, - - /// 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>, -} - -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 { - 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 { - 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::>() - }); - 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> { - 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> { - 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> { - self.node_type_opt(expr.hir_id) - } - - pub fn adjustments(&self) -> LocalTableInContext<'_, Vec>> { - LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments } - } - - pub fn adjustments_mut( - &mut self, - ) -> LocalTableInContextMut<'_, Vec>> { - 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> { - 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 { - 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>> { - LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments } - } - - pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec>> { - 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> { - 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>> { - LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types } - } - - pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec>> { - 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>; - -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct CanonicalUserTypeAnnotation<'tcx> { - pub user_ty: Box>, - 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::::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>, diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 44650827810ab..f785fb5c4b9be 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -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; - -/// 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 -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 SimplifiedTypeGen { - pub fn def(self) -> Option { +impl SimplifiedType { + pub fn def(self) -> Option { match self { AdtSimplifiedType(d) | ForeignSimplifiedType(d) @@ -153,36 +143,6 @@ impl SimplifiedTypeGen { _ => None, } } - - pub fn map_def(self, map: F) -> SimplifiedTypeGen - 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, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5232c1e1cc0f8..7290f0ae7c035 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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 diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index c7d6c6abd1c22..a21e3961cb627 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -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, ty::adjustment::CoerceUnsizedInfo, - ty::fast_reject::SimplifiedTypeGen, + 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, } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b1bc6eb8b81c5..a1d53506707c9 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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 { diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs new file mode 100644 index 0000000000000..4fe85d4366f3e --- /dev/null +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -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 `::X` associated paths and + /// method calls, including those of overloaded operators. + type_dependent_defs: ItemLocalMap>, + + /// 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, + + /// 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>, + + /// 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>, + + /// 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::>()`, then the + /// canonical substitutions would include only `for { Vec }`. + /// + /// See also `AscribeUserType` statement in MIR. + user_provided_types: ItemLocalMap>, + + /// Stores the canonicalized types provided by the user. See also + /// `AscribeUserType` statement in MIR. + pub user_provided_sigs: LocalDefIdMap>, + + adjustments: ItemLocalMap>>, + + /// Stores the actual binding mode for all instances of hir::BindingAnnotation. + pat_binding_modes: ItemLocalMap, + + /// 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, &Option]`. Empty vectors are not stored. + /// + /// See: + /// + pat_adjustments: ItemLocalMap>>, + + /// 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>, + + /// 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>>, + + /// 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>, + + /// If any errors occurred while type-checking this body, + /// this field will be set to `Some(ErrorGuaranteed)`. + pub tainted_by_errors: Option, + + /// 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>, + + /// 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, 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>>, + + /// 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>, +} + +/// 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 of `.await` or `yield` expression. + pub yield_span: Span, + /// Expr which the type evaluated from. + pub expr: Option, +} + +// 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>>, + pub hir_owner: DefId, + pub nodes_types: ItemLocalMap>, + pub adjustments: ItemLocalMap>>, +} + +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 { + 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 { + 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::>() + }); + 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> { + 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> { + 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> { + self.node_type_opt(expr.hir_id) + } + + pub fn adjustments(&self) -> LocalTableInContext<'_, Vec>> { + LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments } + } + + pub fn adjustments_mut( + &mut self, + ) -> LocalTableInContextMut<'_, Vec>> { + 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> { + 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 { + 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>> { + LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments } + } + + pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec>> { + 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> { + 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>> { + LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types } + } + + pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec>> { + 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, +} + +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 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, +} + +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 { + 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 { + 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>; + +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct CanonicalUserTypeAnnotation<'tcx> { + pub user_ty: Box>, + 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::::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>), +} diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index f1ca72de8dbe4..f15cf54718e2b 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -77,3 +77,9 @@ pub struct SymbolAlreadyDefined { pub span: Option, pub symbol: String, } + +#[derive(Diagnostic)] +#[diag(monomorphize_couldnt_dump_mono_stats)] +pub struct CouldntDumpMonoStats { + pub error: String, +} diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 932edc6675f59..38e1d98e44e13 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -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, + crate_name: Option<&str>, +) -> Result<(), Box> { + 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(); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index dab9c736d14d5..9e130287104f9 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -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 = (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], diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 5525eb5331c27..2181c090027b5 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -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> { diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index fb3e4a6c083f8..d9c87ac0ba82b 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -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) + } ) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 3c5e36123ecf5..181316427609e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -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 + } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index dd5085bf4f300..057b0a368bf9b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -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))>>; } 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`. + // Suggest `-> impl Trait`, and if `Trait` is object safe, `-> Box`. 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 { - 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 { + 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 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() // ^^^^^^ ^^^^^^^^^^^ 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 `::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 `::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 { - // `` 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() @@ -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))>> { + 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 `::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 `::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 { + // `` 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!( diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index a995eeb9a7afb..0e0a883d9f590 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -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); - - 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, - )); + 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, + )); + } } ty::ConstKind::Infer(_) => { let cause = self.cause(traits::WellFormed(None)); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 50caef3553fda..d1601272af759 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -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_) { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7a7313c4bc99d..7a13e7e36d169 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -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 = OnceCell::new(); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index bc1e15b359371..a527e9feaec37 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -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); diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index a4097c456135d..de0dfcd469045 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -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; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index a11aba12e0ac7..dd7fc6892537c 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -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) { diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index f697724468fb3..b69d8a1cff957 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -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) { diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 94cf7b94241df..3537e669608d1 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -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) diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.rs b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs index 26b9f4b3a9266..fed60ccf089d0 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.rs +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs @@ -4,5 +4,5 @@ trait I32Iterator = Iterator; fn main() { let _: &dyn I32Iterator = &vec![42].into_iter(); - //~^ ERROR expected `std::vec::IntoIter` to be an iterator that yields `i32`, but it yields `u32` + //~^ ERROR expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` } diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr index 2d25f68de44ad..a28a0b74e4acc 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `std::vec::IntoIter` to be an iterator that yields `i32`, but it yields `u32` +error[E0271]: expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` --> $DIR/associated-types-overridden-binding-2.rs:6:43 | LL | let _: &dyn I32Iterator = &vec![42].into_iter(); diff --git a/src/test/ui/confuse-field-and-method/issue-33784.stderr b/src/test/ui/confuse-field-and-method/issue-33784.stderr index 34debb6831734..3906d64c94624 100644 --- a/src/test/ui/confuse-field-and-method/issue-33784.stderr +++ b/src/test/ui/confuse-field-and-method/issue-33784.stderr @@ -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(); diff --git a/src/test/ui/const-generics/issue-105689.rs b/src/test/ui/const-generics/issue-105689.rs new file mode 100644 index 0000000000000..4237b3cad8e7f --- /dev/null +++ b/src/test/ui/const-generics/issue-105689.rs @@ -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() {} diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr index e1a7a02a56869..0e580aedeaa92 100644 --- a/src/test/ui/empty/empty-struct-braces-expr.stderr +++ b/src/test/ui/empty/empty-struct-braces-expr.stderr @@ -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` diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs index 9b868ed7a9e93..c04e57843d4b2 100644 --- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs +++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs @@ -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 = Box::new(A { v: 22 }); - foo(*x); - //~^ ERROR [E0277] + foo(*x); //~ ERROR [E0277] } diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr index 0f7520ef7f8a9..92c71392672e1 100644 --- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr +++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr @@ -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`. diff --git a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr index c4507843e366e..9aeeb88cf04f2 100644 --- a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr +++ b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr @@ -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()) {} diff --git a/src/test/ui/functions-closures/fn-help-with-err.stderr b/src/test/ui/functions-closures/fn-help-with-err.stderr index 2296666219eef..463ac7684ecdf 100644 --- a/src/test/ui/functions-closures/fn-help-with-err.stderr +++ b/src/test/ui/functions-closures/fn-help-with-err.stderr @@ -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 diff --git a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr index d1d76916b2639..0458d2535f2f5 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr @@ -1,4 +1,4 @@ -error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied +error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:118:22 | LL | pub struct Map { @@ -8,7 +8,7 @@ LL | pub struct Map { | 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` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: `&'a mut &Map: Stream` @@ -19,7 +19,7 @@ note: the following trait bounds were not satisfied: LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here -error[E0599]: the method `countx` exists for struct `Filter fn(&'a u64) -> &'a u64 {identity::}>, [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 fn(&'a u64) -> &'a u64 {identity::}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:130:24 | LL | pub struct Filter { diff --git a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr index ab5598e364fc4..fdd192f431370 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr @@ -30,7 +30,7 @@ LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::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( diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index f90399b6b9458..7f73d5e12d196 100644 --- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -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!() } diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 3d4ae11e57670..548c89d0a3871 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -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 diff --git a/src/test/ui/issues/issue-18107.stderr b/src/test/ui/issues/issue-18107.stderr index 28478457b296d..1669b550a9baf 100644 --- a/src/test/ui/issues/issue-18107.stderr +++ b/src/test/ui/issues/issue-18107.stderr @@ -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 diff --git a/src/test/ui/issues/issue-30123.stderr b/src/test/ui/issues/issue-30123.stderr index e9d934332f171..7808cbf8aa108 100644 --- a/src/test/ui/issues/issue-30123.stderr +++ b/src/test/ui/issues/issue-30123.stderr @@ -1,8 +1,8 @@ -error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph` in the current scope +error[E0599]: no function or associated item named `new_undirected` found for struct `Graph` in the current scope --> $DIR/issue-30123.rs:7:33 | LL | let ug = Graph::::new_undirected(); - | ^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph` + | ^^^^^^^^^^^^^^ function or associated item not found in `Graph` | = note: the function or associated item was found for - `issue_30123_aux::Graph` diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index a32359c2b9f79..f3be99f9bcb4b 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter, [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, [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) { + | ^^^^^^^^^^^^^^^^^ `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, [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, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied --> $DIR/issue-31173.rs:12:10 | LL | .collect(); diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs index 8430e85df8715..e3b6dcf55a744 100644 --- a/src/test/ui/issues/issue-33941.rs +++ b/src/test/ui/issues/issue-33941.rs @@ -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 `(&_, &_)` } diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index 49702c4765863..668eaabca4c46 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -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>` to implement `Iterator` = note: required for `Cloned>` 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() {} diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr index fd694df30457e..00c375f8d2acf 100644 --- a/src/test/ui/issues/issue-41880.stderr +++ b/src/test/ui/issues/issue-41880.stderr @@ -5,7 +5,7 @@ LL | pub struct Iterate { | ------------------------ method `iter` not found for this struct ... LL | println!("{:?}", a.iter().take(10).collect::>()); - | ^^^^ 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 diff --git a/src/test/ui/issues/issue-42312.stderr b/src/test/ui/issues/issue-42312.stderr index 6fe151622433a..3ca6a2957e14b 100644 --- a/src/test/ui/issues/issue-42312.stderr +++ b/src/test/ui/issues/issue-42312.stderr @@ -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) {} diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr index 8a20a60853a63..ffff403e0d465 100644 --- a/src/test/ui/issues/issue-5883.stderr +++ b/src/test/ui/issues/issue-5883.stderr @@ -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 diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs index 87116e4924570..ebdf33303c982 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.rs +++ b/src/test/ui/iterators/invalid-iterator-chain.rs @@ -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 { + 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 = f.collect(); //~ ERROR E0277 + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); } diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr index 84bac7833f67b..d76a4bfb7b3ea 100644 --- a/src/test/ui/iterators/invalid-iterator-chain.stderr +++ b/src/test/ui/iterators/invalid-iterator-chain.stderr @@ -1,5 +1,23 @@ +error[E0277]: a value of type `Vec` 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` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<&X>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` +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 { + | ^^^^^^^^^^^ `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::()); | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -9,7 +27,7 @@ LL | println!("{}", scores.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::(), | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -34,7 +52,7 @@ LL | .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::(), | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -66,7 +84,7 @@ LL | .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::()); | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -94,7 +112,7 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).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::()); | ---------- ------ ^^^^^^^^^^^^^^^ `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::()); | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` @@ -115,7 +133,7 @@ LL | println!("{}", vec![(), ()].iter().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::()); | ------------ ^^^^^^ `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` 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 = f.collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` @@ -133,7 +151,7 @@ LL | let g: Vec = f.collect(); = help: the trait `FromIterator<()>` is not implemented for `Vec` = help: the trait `FromIterator` is implemented for `Vec` 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`. diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr index fc42d1a4dcd08..8846efba871b9 100644 --- a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr +++ b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr @@ -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, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:21]>` + | ^^^^^^ method not found in `Map, [closure@method-not-found-generic-arg-elision.rs:87:18]>` error[E0599]: no method named `method` found for struct `Wrapper` in the current scope --> $DIR/method-not-found-generic-arg-elision.rs:90:13 diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 3151bc76891e4..72fb0e4d77431 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -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>, [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>, [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(); diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr index 45cf3723483f3..a0f790dba15ed 100644 --- a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -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 || { diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr index 939392733f0e9..558e6b7b118d8 100644 --- a/src/test/ui/resolve/issue-5035-2.stderr +++ b/src/test/ui/resolve/issue-5035-2.stderr @@ -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) {} diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed new file mode 100644 index 0000000000000..4f9e93a47ed1c --- /dev/null +++ b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed @@ -0,0 +1,16 @@ +// run-rustfix +fn wat(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); +} diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs new file mode 100644 index 0000000000000..89b077d671a51 --- /dev/null +++ b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs @@ -0,0 +1,15 @@ +// run-rustfix +fn wat(t: &T) -> T { + t.clone() //~ ERROR E0308 +} + +struct Foo; + +fn wut(t: &Foo) -> Foo { + t.clone() //~ ERROR E0308 +} + +fn main() { + wat(&42); + wut(&Foo); +} diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr new file mode 100644 index 0000000000000..26ab515d9b4b6 --- /dev/null +++ b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr @@ -0,0 +1,43 @@ +error[E0308]: mismatched types + --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5 + | +LL | fn wat(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: &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`. diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 2cb53ecce1040..6910b77d9bc3f 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -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` diff --git a/src/test/ui/traits/assoc-type-in-superbad.rs b/src/test/ui/traits/assoc-type-in-superbad.rs index d7d6241ef708c..65340b2a2092f 100644 --- a/src/test/ui/traits/assoc-type-in-superbad.rs +++ b/src/test/ui/traits/assoc-type-in-superbad.rs @@ -10,7 +10,7 @@ pub trait Foo: Iterator::Key> { impl Foo for IntoIter { type Key = u32; - //~^ ERROR expected `std::vec::IntoIter` to be an iterator that yields `u32`, but it yields `i32` + //~^ ERROR expected `IntoIter` to be an iterator that yields `u32`, but it yields `i32` } fn main() {} diff --git a/src/test/ui/traits/assoc-type-in-superbad.stderr b/src/test/ui/traits/assoc-type-in-superbad.stderr index 3e2d9d9038aa7..7fa1d2c2eed67 100644 --- a/src/test/ui/traits/assoc-type-in-superbad.stderr +++ b/src/test/ui/traits/assoc-type-in-superbad.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `std::vec::IntoIter` to be an iterator that yields `u32`, but it yields `i32` +error[E0271]: expected `IntoIter` to be an iterator that yields `u32`, but it yields `i32` --> $DIR/assoc-type-in-superbad.rs:12:16 | LL | type Key = u32; diff --git a/src/test/ui/traits/bound/not-on-bare-trait.stderr b/src/test/ui/traits/bound/not-on-bare-trait.stderr index 8da0b6d6b8505..36b08a7d30931 100644 --- a/src/test/ui/traits/bound/not-on-bare-trait.stderr +++ b/src/test/ui/traits/bound/not-on-bare-trait.stderr @@ -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) { diff --git a/src/test/ui/type-alias-impl-trait/issue-57961.rs b/src/test/ui/type-alias-impl-trait/issue-57961.rs index 24b3a045856a6..4aa5966ff25d4 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57961.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57961.rs @@ -8,7 +8,7 @@ trait Foo { impl Foo for () { type Bar = std::vec::IntoIter; - //~^ ERROR expected `std::vec::IntoIter` to be an iterator that yields `X`, but it yields `u32` + //~^ ERROR expected `IntoIter` to be an iterator that yields `X`, but it yields `u32` } fn incoherent() { diff --git a/src/test/ui/type-alias-impl-trait/issue-57961.stderr b/src/test/ui/type-alias-impl-trait/issue-57961.stderr index fb40895c49f15..8d11b48888947 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57961.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57961.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `std::vec::IntoIter` to be an iterator that yields `X`, but it yields `u32` +error[E0271]: expected `IntoIter` to be an iterator that yields `X`, but it yields `u32` --> $DIR/issue-57961.rs:10:16 | LL | type X = impl Sized; diff --git a/src/test/ui/typeck/explain_clone_autoref.stderr b/src/test/ui/typeck/explain_clone_autoref.stderr index faac680ea1931..ff36e18d28301 100644 --- a/src/test/ui/typeck/explain_clone_autoref.stderr +++ b/src/test/ui/typeck/explain_clone_autoref.stderr @@ -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 diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr index e5ca0edd7a91c..99ec517834003 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr @@ -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 diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 90192f46cbfa0..652f8b4d3c56e 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -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, };