self.with_catch_scope(body.id, |this| {
let mut block = this.lower_block_noalloc(body, true);
- let try_span = this.mark_span_with_reason(
- DesugaringKind::TryBlock,
- body.span,
- this.allow_try_trait.clone(),
- );
-
// Final expression of the block (if present) or `()` with span at the end of block
- let tail_expr = block
- .expr
- .take()
- .unwrap_or_else(|| this.expr_unit(this.sess.source_map().end_point(try_span)));
+ let (try_span, tail_expr) = if let Some(expr) = block.expr.take() {
+ (
+ this.mark_span_with_reason(
+ DesugaringKind::TryBlock,
+ expr.span,
+ this.allow_try_trait.clone(),
+ ),
+ expr,
+ )
+ } else {
+ let try_span = this.mark_span_with_reason(
+ DesugaringKind::TryBlock,
+ this.sess.source_map().end_point(body.span),
+ this.allow_try_trait.clone(),
+ );
+
+ (try_span, this.expr_unit(try_span))
+ };
let ok_wrapped_span =
this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
hir::LangItem::TryFromError,
unstable_span,
from_expr,
- try_span,
+ unstable_span,
);
let thin_attrs = ThinVec::from(attrs);
let catch_scope = self.catch_scopes.last().copied();
For example:
```compile_fail,E0284
-fn foo() -> Result<bool, ()> {
- let results = [Ok(true), Ok(false), Err(())].iter().cloned();
- let v: Vec<bool> = results.collect()?;
- // Do things with v...
- Ok(true)
+fn main() {
+ let n: u32 = 1;
+ let mut d: u64 = 2;
+ d = d + n.into();
}
```
-Here we have an iterator `results` over `Result<bool, ()>`.
-Hence, `results.collect()` can return any type implementing
-`FromIterator<Result<bool, ()>>`. On the other hand, the
-`?` operator can accept any type implementing `Try`.
+Here we have an addition of `d` and `n.into()`. Hence, `n.into()` can return
+any type `T` where `u64: Add<T>`. On the other hand, the `into` method can
+return any type where `u32: Into<T>`.
-The author of this code probably wants `collect()` to return a
-`Result<Vec<bool>, ()>`, but the compiler can't be sure
-that there isn't another type `T` implementing both `Try` and
-`FromIterator<Result<bool, ()>>` in scope such that
-`T::Ok == Vec<bool>`. Hence, this code is ambiguous and an error
-is returned.
+The author of this code probably wants `into()` to return a `u64`, but the
+compiler can't be sure that there isn't another type `T` where both
+`u32: Into<T>` and `u64: Add<T>`.
To resolve this error, use a concrete type for the intermediate expression:
```
-fn foo() -> Result<bool, ()> {
- let results = [Ok(true), Ok(false), Err(())].iter().cloned();
- let v = {
- let temp: Result<Vec<bool>, ()> = results.collect();
- temp?
- };
- // Do things with v...
- Ok(true)
+fn main() {
+ let n: u32 = 1;
+ let mut d: u64 = 2;
+ let m: u64 = n.into();
+ d = d + m;
}
```
//! the end of the file for details.
use super::combine::CombineFields;
-use super::{HigherRankedType, InferCtxt, PlaceholderMap};
+use super::{HigherRankedType, InferCtxt};
use crate::infer::CombinedSnapshot;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
self.infcx.commit_if_ok(|_| {
// First, we instantiate each bound region in the supertype with a
// fresh placeholder region.
- let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(&b);
+ let b_prime = self.infcx.replace_bound_vars_with_placeholders(&b);
// Next, we instantiate each bound region in the subtype
// with a fresh region variable. These region variables --
/// the [rustc dev guide].
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
- pub fn replace_bound_vars_with_placeholders<T>(
- &self,
- binder: &ty::Binder<T>,
- ) -> (T, PlaceholderMap<'tcx>)
+ pub fn replace_bound_vars_with_placeholders<T>(&self, binder: &ty::Binder<T>) -> T
where
T: TypeFoldable<'tcx>,
{
next_universe, binder, result, map,
);
- (result, map)
+ result
}
/// See `infer::region_constraints::RegionConstraintCollector::leak_check`.
universe: Cell<ty::UniverseIndex>,
}
-/// A map returned by `replace_bound_vars_with_placeholders()`
-/// indicating the placeholder region that each late-bound region was
-/// replaced with.
-pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
-
/// See the `error_reporting` module for more details.
#[derive(Clone, Debug, PartialEq, Eq, TypeFoldable)]
pub enum ValuePairs<'tcx> {
}
Some(self.commit_if_ok(|_snapshot| {
- let (ty::SubtypePredicate { a_is_expected, a, b }, _) =
+ let ty::SubtypePredicate { a_is_expected, a, b } =
self.replace_bound_vars_with_placeholders(&predicate);
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
) -> UnitResult<'tcx> {
self.commit_if_ok(|_snapshot| {
- let (ty::OutlivesPredicate(r_a, r_b), _) =
+ let ty::OutlivesPredicate(r_a, r_b) =
self.replace_bound_vars_with_placeholders(&predicate);
let origin = SubregionOrigin::from_obligation_cause(cause, || {
RelateRegionParamBound(cause.span)
assoc_item_def_id: DefId,
) -> impl Iterator<Item = ty::Region<'tcx>> {
let tcx = self.tcx;
- let predicates = tcx.projection_predicates(assoc_item_def_id);
- predicates
+ let bounds = tcx.item_bounds(assoc_item_def_id);
+ bounds
.into_iter()
.filter_map(|p| p.to_opt_type_outlives())
.filter_map(|p| p.no_bound_vars())
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
-use rustc_span::Span;
pub fn anonymize_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
) -> Elaborator<'tcx> {
- let obligations = predicates.map(|predicate| predicate_obligation(predicate, None)).collect();
+ let obligations = predicates
+ .map(|predicate| {
+ predicate_obligation(predicate, ty::ParamEnv::empty(), ObligationCause::dummy())
+ })
+ .collect();
elaborate_obligations(tcx, obligations)
}
fn predicate_obligation<'tcx>(
predicate: ty::Predicate<'tcx>,
- span: Option<Span>,
+ param_env: ty::ParamEnv<'tcx>,
+ cause: ObligationCause<'tcx>,
) -> PredicateObligation<'tcx> {
- let cause = if let Some(span) = span {
- ObligationCause::dummy_with_span(span)
- } else {
- ObligationCause::dummy()
- };
-
- Obligation { cause, param_env: ty::ParamEnv::empty(), recursion_depth: 0, predicate }
+ Obligation { cause, param_env, recursion_depth: 0, predicate }
}
impl Elaborator<'tcx> {
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());
- let obligations = predicates.predicates.iter().map(|&(pred, span)| {
+ let obligations = predicates.predicates.iter().map(|&(pred, _)| {
predicate_obligation(
pred.subst_supertrait(tcx, &ty::Binder::bind(data.trait_ref)),
- Some(span),
+ obligation.param_env,
+ obligation.cause.clone(),
)
});
debug!("super_predicates: data={:?}", data);
})
.map(|predicate_kind| predicate_kind.to_predicate(tcx))
.filter(|&predicate| visited.insert(predicate))
- .map(|predicate| predicate_obligation(predicate, None)),
+ .map(|predicate| {
+ predicate_obligation(
+ predicate,
+ obligation.param_env,
+ obligation.cause.clone(),
+ )
+ }),
);
}
ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
ty::Adt(def, _) => check_must_use_def(cx, def.did, span, descr_pre, descr_post),
ty::Opaque(def, _) => {
let mut has_emitted = false;
- for (predicate, _) in cx.tcx.predicates_of(def).predicates {
+ for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
// We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateAtom::Trait(ref poly_trait_predicate, _) =
predicate.skip_binders()
.tables
.inferred_outlives
.get(self, item_id)
- .map(|predicates| predicates.decode((self, tcx)))
+ .map(|predicates| tcx.arena.alloc_from_iter(predicates.decode((self, tcx))))
.unwrap_or_default()
}
self.root.tables.super_predicates.get(self, item_id).unwrap().decode((self, tcx))
}
+ fn get_explicit_item_bounds(
+ &self,
+ item_id: DefIndex,
+ tcx: TyCtxt<'tcx>,
+ ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+ self.root
+ .tables
+ .explicit_item_bounds
+ .get(self, item_id)
+ .map(|bounds| tcx.arena.alloc_from_iter(bounds.decode((self, tcx))))
+ .unwrap_or_default()
+ }
+
fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess))
}
explicit_predicates_of => { cdata.get_explicit_predicates(def_id.index, tcx) }
inferred_outlives_of => { cdata.get_inferred_outlives(def_id.index, tcx) }
super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
+ explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) }
trait_def => { cdata.get_trait_def(def_id.index, tcx.sess) }
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
adt_destructor => {
record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
}
+ fn encode_explicit_item_bounds(&mut self, def_id: DefId) {
+ debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
+ let bounds = self.tcx.explicit_item_bounds(def_id);
+ if !bounds.is_empty() {
+ record!(self.tables.explicit_item_bounds[def_id] <- bounds);
+ }
+ }
+
fn encode_info_for_trait_item(&mut self, def_id: DefId) {
debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
let tcx = self.tcx;
has_self: trait_item.fn_has_self_parameter,
}))
}
- ty::AssocKind::Type => EntryKind::AssocType(container),
+ ty::AssocKind::Type => {
+ self.encode_explicit_item_bounds(def_id);
+ EntryKind::AssocType(container)
+ }
});
record!(self.tables.visibility[def_id] <- trait_item.vis);
record!(self.tables.span[def_id] <- ast_item.span);
hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
hir::ItemKind::TyAlias(..) => EntryKind::Type,
- hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy,
+ hir::ItemKind::OpaqueTy(..) => {
+ self.encode_explicit_item_bounds(def_id);
+ EntryKind::OpaqueTy
+ }
hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr),
hir::ItemKind::Struct(ref struct_def, _) => {
let adt_def = self.tcx.adt_def(def_id);
generics: Table<DefIndex, Lazy<ty::Generics>>,
explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
expn_that_defined: Table<DefIndex, Lazy<ExpnId>>,
- // FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate`
- // doesn't handle shorthands in its own (de)serialization impls,
- // as it's an `enum` for which we want to derive (de)serialization,
- // so the `ty::codec` APIs handle the whole `&'tcx [...]` at once.
- // Also, as an optimization, a missing entry indicates an empty `&[]`.
- inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
+ // As an optimization, a missing entry indicates an empty `&[]`.
+ inferred_outlives: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
+ // As an optimization, a missing entry indicates an empty `&[]`.
+ explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
cache_on_disk_if { key.is_local() }
}
- /// Returns the list of predicates that can be used for
- /// `SelectionCandidate::ProjectionCandidate` and
+ /// Returns the list of bounds that can be used for
+ /// `SelectionCandidate::ProjectionCandidate(_)` and
/// `ProjectionTyCandidate::TraitDef`.
- /// Specifically this is the bounds (equivalent to) those
- /// written on the trait's type definition, or those
- /// after the `impl` keyword
+ /// Specifically this is the bounds written on the trait's type
+ /// definition, or those after the `impl` keyword
///
/// type X: Bound + 'lt
/// ^^^^^^^^^^^
/// ^^^^^^^^^^^^^^^
///
/// `key` is the `DefId` of the associated type or opaque type.
- query projection_predicates(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
- desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) }
+ ///
+ /// Bounds from the parent (e.g. with nested impl trait) are not included.
+ query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+ desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
+ }
+
+ /// Elaborated version of the predicates from `explicit_item_bounds`.
+ ///
+ /// Example for
+ ///
+ /// trait MyTrait {
+ /// type MyAType: Eq + ?Sized`
+ /// }
+ ///
+ /// `explicit_item_bounds` returns `[<Self as MyTrait>::MyAType: Eq]`,
+ /// and `item_bounds` returns
+ /// [
+ /// <Self as Trait>::MyAType: Eq,
+ /// <Self as Trait>::MyAType: PartialEq<<Self as Trait>::MyAType>
+ /// ]
+ ///
+ /// Bounds from the parent (e.g. with nested impl trait) are not included.
+ query item_bounds(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
+ desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
}
query projection_ty_from_predicates(key: (DefId, DefId)) -> Option<ty::ProjectionTy<'tcx>> {
desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) }
}
+ /// Returns everything that looks like a predicate written explicitly
+ /// by the user on a trait item.
+ ///
+ /// Traits are unusual, because predicates on associated types are
+ /// converted into bounds on that type for backwards compatibility:
+ ///
+ /// trait X where Self::U: Copy { type U; }
+ ///
+ /// becomes
+ ///
+ /// trait X { type U: Copy; }
+ ///
+ /// `explicit_predicates_of` and `explicit_item_bounds` will then take
+ /// the appropriate subsets of the predicates here.
+ query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> {
+ desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key.to_def_id()) }
+ }
+
/// Returns the predicates written explicitly by the user.
query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
ImplCandidate(DefId),
AutoImplCandidate(DefId),
- /// This is a trait matching with a projected type as `Self`, and
- /// we found an applicable bound in the trait definition.
- ProjectionCandidate,
+ /// This is a trait matching with a projected type as `Self`, and we found
+ /// an applicable bound in the trait definition. The `usize` is an index
+ /// into the list returned by `tcx.item_bounds`.
+ ProjectionCandidate(usize),
/// Implementation of a `Fn`-family trait by one of the anonymous types
/// generated for a `||` expression.
}
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
- let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
+ let bounds = self.tcx().explicit_item_bounds(def_id);
let mut first = true;
let mut is_sized = false;
p!("impl");
- for predicate in bounds.predicates {
+ for (predicate, _) in bounds {
+ let predicate = predicate.subst(self.tcx(), substs);
// Note: We can't use `to_opt_poly_trait_ref` here as `predicate`
// may contain unbound variables. We therefore do this manually.
//
/// then this function would return a `exists T. T: Iterator` existential trait
/// reference.
pub fn trait_ref(&self, tcx: TyCtxt<'_>) -> ty::ExistentialTraitRef<'tcx> {
+ // FIXME(generic_associated_types): substs is the substs of the
+ // associated type, which should be truncated to get the correct substs
+ // for the trait.
let def_id = tcx.associated_item(self.item_def_id).container.id();
ty::ExistentialTraitRef { def_id, substs: self.substs }
}
error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin,
};
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
+use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_span::symbol::{kw, sym};
use rustc_span::Span;
//
// eg. check for `impl Trait + 'static` instead of `impl Trait`.
let has_static_predicate = {
- let predicates_of = self.infcx.tcx.predicates_of(did);
- let bounds = predicates_of.instantiate(self.infcx.tcx, substs);
+ let bounds = self.infcx.tcx.explicit_item_bounds(did);
let mut found = false;
- for predicate in bounds.predicates {
+ for (bound, _) in bounds {
if let ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_, r)) =
- predicate.skip_binders()
+ bound.skip_binders()
{
+ let r = r.subst(self.infcx.tcx, substs);
if let ty::RegionKind::ReStatic = r {
found = true;
break;
// The intent is to treat `impl Trait1 + Trait2` identically to
// `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
// (it either has no visibility, or its visibility is insignificant, like
- // visibilities of type aliases) and recurse into predicates instead to go
+ // visibilities of type aliases) and recurse into bounds instead to go
// through the trait list (default type visitor doesn't visit those traits).
// All traits in the list are considered the "primary" part of the type
// and are visited by shallow visitors.
- if self.visit_predicates(tcx.predicates_of(def_id)) {
+ if self.visit_predicates(ty::GenericPredicates {
+ parent: None,
+ predicates: tcx.explicit_item_bounds(def_id),
+ }) {
return true;
}
}
self
}
+ fn bounds(&mut self) -> &mut Self {
+ self.visit_predicates(ty::GenericPredicates {
+ parent: None,
+ predicates: self.tcx.explicit_item_bounds(self.item_def_id),
+ });
+ self
+ }
+
fn ty(&mut self) -> &mut Self {
self.visit(self.tcx.type_of(self.item_def_id));
self
hir::ItemKind::OpaqueTy(..) => {
// `ty()` for opaque types is the underlying type,
// it's not a part of interface, so we skip it.
- self.check(item.hir_id, item_visibility).generics().predicates();
+ self.check(item.hir_id, item_visibility).generics().bounds();
}
hir::ItemKind::Trait(.., trait_item_refs) => {
self.check(item.hir_id, item_visibility).generics().predicates();
trait_item_ref.defaultness,
item_visibility,
);
+
+ if let AssocItemKind::Type = trait_item_ref.kind {
+ self.check(trait_item_ref.id.hir_id, item_visibility).bounds();
+ }
}
}
hir::ItemKind::TraitAlias(..) => {
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{self, InferCtxt, InferOk};
use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
+use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::config::nightly_options;
use rustc_span::Span;
// If there are required region bounds, we can use them.
if opaque_defn.has_required_region_bounds {
- let predicates_of = tcx.predicates_of(def_id);
- debug!("constrain_opaque_type: predicates: {:#?}", predicates_of,);
- let bounds = predicates_of.instantiate(tcx, opaque_defn.substs);
+ let bounds = tcx.explicit_item_bounds(def_id);
+ debug!("constrain_opaque_type: predicates: {:#?}", bounds);
+ let bounds: Vec<_> =
+ bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_defn.substs)).collect();
debug!("constrain_opaque_type: bounds={:#?}", bounds);
let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
let required_region_bounds =
- required_region_bounds(tcx, opaque_type, bounds.predicates.into_iter());
+ required_region_bounds(tcx, opaque_type, bounds.into_iter());
debug_assert!(!required_region_bounds.is_empty());
for required_region in required_region_bounds {
let ty_var = infcx
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
- let predicates_of = tcx.predicates_of(def_id);
- debug!("instantiate_opaque_types: predicates={:#?}", predicates_of,);
- let bounds = predicates_of.instantiate(tcx, substs);
+ let item_bounds = tcx.explicit_item_bounds(def_id);
+ debug!("instantiate_opaque_types: bounds={:#?}", item_bounds);
+ let bounds: Vec<_> =
+ item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect();
let param_env = tcx.param_env(def_id);
let InferOk { value: bounds, obligations } =
debug!("instantiate_opaque_types: bounds={:?}", bounds);
- let required_region_bounds =
- required_region_bounds(tcx, ty, bounds.predicates.iter().cloned());
+ let required_region_bounds = required_region_bounds(tcx, ty, bounds.iter().copied());
debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
// Make sure that we are in fact defining the *entire* type
);
debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
- for predicate in &bounds.predicates {
+ for predicate in &bounds {
if let ty::PredicateAtom::Projection(projection) = predicate.skip_binders() {
if projection.ty.references_error() {
// No point on adding these obligations since there's a type error involved.
}
}
- self.obligations.reserve(bounds.predicates.len());
- for predicate in bounds.predicates {
+ self.obligations.reserve(bounds.len());
+ for predicate in bounds {
// Change the predicate to refer to the type variable,
// which will be the concrete type instead of the opaque type.
// This also instantiates nested instances of `impl Trait`.
let predicate = self.instantiate_opaque_types_in_map(&predicate);
- let cause = traits::ObligationCause::new(span, self.body_id, traits::SizedReturnType);
+ let cause = traits::ObligationCause::new(span, self.body_id, traits::MiscObligation);
// Require that the predicate holds for the concrete type.
debug!("instantiate_opaque_types: predicate={:?}", predicate);
| ty::PredicateAtom::Subtype(_)
| ty::PredicateAtom::ConstEvaluatable(..)
| ty::PredicateAtom::ConstEquate(..) => {
- let (pred, _) = infcx.replace_bound_vars_with_placeholders(binder);
+ let pred = infcx.replace_bound_vars_with_placeholders(binder);
ProcessResult::Changed(mk_pending(vec![
obligation.with(pred.to_predicate(self.selcx.tcx())),
]))
self.selcx.infcx(),
obligation.param_env,
obligation.cause.body_id,
+ obligation.recursion_depth + 1,
arg,
obligation.cause.span,
) {
Ok(Ok(None)) => {
*stalled_on = trait_ref_infer_vars(
self.selcx,
- project_obligation.predicate.to_poly_trait_ref(self.selcx.tcx()),
+ project_obligation.predicate.to_poly_trait_ref(tcx),
);
ProcessResult::Unchanged
}
if !spans.is_empty() {
violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
}
+ let spans = bounds_reference_self(tcx, trait_def_id);
+ if !spans.is_empty() {
+ violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
+ }
violations.extend(
tcx.associated_items(trait_def_id)
} else {
tcx.predicates_of(trait_def_id)
};
- let self_ty = tcx.types.self_param;
- let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into());
predicates
.predicates
.iter()
- .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
- .filter_map(|(predicate, &sp)| {
- match predicate.skip_binders() {
- ty::PredicateAtom::Trait(ref data, _) => {
- // In the case of a trait predicate, we can skip the "self" type.
- if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
- }
- ty::PredicateAtom::Projection(ref data) => {
- // And similarly for projections. This should be redundant with
- // the previous check because any projection should have a
- // matching `Trait` predicate with the same inputs, but we do
- // the check to be safe.
- //
- // Note that we *do* allow projection *outputs* to contain
- // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
- // we just require the user to specify *both* outputs
- // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
- //
- // This is ALT2 in issue #56288, see that for discussion of the
- // possible alternatives.
- if data.projection_ty.trait_ref(tcx).substs[1..].iter().any(has_self_ty) {
- Some(sp)
- } else {
- None
- }
- }
- ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::TypeOutlives(..)
- | ty::PredicateAtom::RegionOutlives(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
- }
- })
+ .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), *sp))
+ .filter_map(|predicate| predicate_references_self(tcx, predicate))
+ .collect()
+}
+
+fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
+ let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
+ tcx.associated_items(trait_def_id)
+ .in_definition_order()
+ .filter(|item| item.kind == ty::AssocKind::Type)
+ .flat_map(|item| tcx.explicit_item_bounds(item.def_id))
+ .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), *sp))
+ .filter_map(|predicate| predicate_references_self(tcx, predicate))
.collect()
}
+fn predicate_references_self(
+ tcx: TyCtxt<'tcx>,
+ (predicate, sp): (ty::Predicate<'tcx>, Span),
+) -> Option<Span> {
+ let self_ty = tcx.types.self_param;
+ let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into());
+ match predicate.skip_binders() {
+ ty::PredicateAtom::Trait(ref data, _) => {
+ // In the case of a trait predicate, we can skip the "self" type.
+ if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+ }
+ ty::PredicateAtom::Projection(ref data) => {
+ // And similarly for projections. This should be redundant with
+ // the previous check because any projection should have a
+ // matching `Trait` predicate with the same inputs, but we do
+ // the check to be safe.
+ //
+ // It's also won't be redundant if we allow type-generic associated
+ // types for trait objects.
+ //
+ // Note that we *do* allow projection *outputs* to contain
+ // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
+ // we just require the user to specify *both* outputs
+ // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
+ //
+ // This is ALT2 in issue #56288, see that for discussion of the
+ // possible alternatives.
+ if data.projection_ty.trait_ref(tcx).substs[1..].iter().any(has_self_ty) {
+ Some(sp)
+ } else {
+ None
+ }
+ }
+ ty::PredicateAtom::WellFormed(..)
+ | ty::PredicateAtom::ObjectSafe(..)
+ | ty::PredicateAtom::TypeOutlives(..)
+ | ty::PredicateAtom::RegionOutlives(..)
+ | ty::PredicateAtom::ClosureKind(..)
+ | ty::PredicateAtom::Subtype(..)
+ | ty::PredicateAtom::ConstEvaluatable(..)
+ | ty::PredicateAtom::ConstEquate(..)
+ | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+ }
+}
+
fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
generics_require_sized_self(tcx, trait_def_id)
}
//! Code for projecting associated types out of trait references.
-use super::elaborate_predicates;
use super::specialization_graph;
use super::translate_substs;
use super::util;
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_span::symbol::sym;
-use rustc_span::DUMMY_SP;
pub use rustc_middle::traits::Reveal;
#[derive(PartialEq, Eq, Debug)]
enum ProjectionTyCandidate<'tcx> {
- // from a where-clause in the env or object type
+ /// From a where-clause in the env or object type
ParamEnv(ty::PolyProjectionPredicate<'tcx>),
- // from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
+ /// From the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
TraitDef(ty::PolyProjectionPredicate<'tcx>),
- // from a "impl" (or a "pseudo-impl" returned by select)
+ /// Bounds specified on an object type
+ Object(ty::PolyProjectionPredicate<'tcx>),
+
+ /// From a "impl" (or a "pseudo-impl" returned by select)
Select(Selection<'tcx>),
}
let infcx = selcx.infcx();
infcx.commit_if_ok(|_snapshot| {
- let (placeholder_predicate, _) =
+ let placeholder_predicate =
infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
let placeholder_obligation = obligation.with(placeholder_predicate);
} else {
obligations.extend(ty.obligations);
}
-
- obligations.push(get_paranoid_cache_value_obligation(
- infcx,
- param_env,
- projection_ty,
- cause,
- depth,
- ));
return Ok(Some(ty.value));
}
Err(ProjectionCacheEntry::Error) => {
NormalizedTy { value: result.value, obligations }
}
-/// Whenever we give back a cache result for a projection like `<T as
-/// Trait>::Item ==> X`, we *always* include the obligation to prove
-/// that `T: Trait` (we may also include some other obligations). This
-/// may or may not be necessary -- in principle, all the obligations
-/// that must be proven to show that `T: Trait` were also returned
-/// when the cache was first populated. But there are some vague concerns,
-/// and so we take the precautionary measure of including `T: Trait` in
-/// the result:
-///
-/// Concern #1. The current setup is fragile. Perhaps someone could
-/// have failed to prove the concerns from when the cache was
-/// populated, but also not have used a snapshot, in which case the
-/// cache could remain populated even though `T: Trait` has not been
-/// shown. In this case, the "other code" is at fault -- when you
-/// project something, you are supposed to either have a snapshot or
-/// else prove all the resulting obligations -- but it's still easy to
-/// get wrong.
-///
-/// Concern #2. Even within the snapshot, if those original
-/// obligations are not yet proven, then we are able to do projections
-/// that may yet turn out to be wrong. This *may* lead to some sort
-/// of trouble, though we don't have a concrete example of how that
-/// can occur yet. But it seems risky at best.
-fn get_paranoid_cache_value_obligation<'a, 'tcx>(
- infcx: &'a InferCtxt<'a, 'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- projection_ty: ty::ProjectionTy<'tcx>,
- cause: ObligationCause<'tcx>,
- depth: usize,
-) -> PredicateObligation<'tcx> {
- let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
- Obligation {
- cause,
- recursion_depth: depth,
- param_env,
- predicate: trait_ref.without_const().to_predicate(infcx.tcx),
- }
-}
-
/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
/// hold. In various error cases, we cannot generate a valid
/// normalized projection. Therefore, we create an inference variable
assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
- assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
+ assemble_candidates_from_object_ty(selcx, obligation, &obligation_trait_ref, &mut candidates);
+
+ if let ProjectionTyCandidateSet::Single(ProjectionTyCandidate::Object(_)) = candidates {
+ // Avoid normalization cycle from selection (see
+ // `assemble_candidates_from_object_ty`).
+ // FIXME(lazy_normalization): Lazy normalization should save us from
+ // having to do special case this.
+ } else {
+ assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
+ };
match candidates {
- ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress(
- confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate),
- )),
+ ProjectionTyCandidateSet::Single(candidate) => {
+ Ok(ProjectedTy::Progress(confirm_candidate(selcx, obligation, candidate)))
+ }
ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
selcx
.tcx()
candidate_set,
ProjectionTyCandidate::ParamEnv,
obligation.param_env.caller_bounds().iter(),
+ false,
);
}
// Check whether the self-type is itself a projection.
// If so, extract what we know from the trait and try to come up with a good answer.
let bounds = match *obligation_trait_ref.self_ty().kind() {
- ty::Projection(ref data) => {
- tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
- }
- ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
+ ty::Projection(ref data) => tcx.item_bounds(data.item_def_id).subst(tcx, data.substs),
+ ty::Opaque(def_id, substs) => tcx.item_bounds(def_id).subst(tcx, substs),
ty::Infer(ty::TyVar(_)) => {
// If the self-type is an inference variable, then it MAY wind up
// being a projected type, so induce an ambiguity.
candidate_set,
ProjectionTyCandidate::TraitDef,
bounds.iter(),
+ true,
)
}
+/// In the case of a trait object like
+/// `<dyn Iterator<Item = ()> as Iterator>::Item` we can use the existential
+/// predicate in the trait object.
+///
+/// We don't go through the select candidate for these bounds to avoid cycles:
+/// In the above case, `dyn Iterator<Item = ()>: Iterator` would create a
+/// nested obligation of `<dyn Iterator<Item = ()> as Iterator>::Item: Sized`,
+/// this then has to be normalized without having to prove
+/// `dyn Iterator<Item = ()>: Iterator` again.
+fn assemble_candidates_from_object_ty<'cx, 'tcx>(
+ selcx: &mut SelectionContext<'cx, 'tcx>,
+ obligation: &ProjectionTyObligation<'tcx>,
+ obligation_trait_ref: &ty::TraitRef<'tcx>,
+ candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+) {
+ debug!("assemble_candidates_from_object_ty(..)");
+
+ let tcx = selcx.tcx();
+
+ let self_ty = obligation_trait_ref.self_ty();
+ let object_ty = selcx.infcx().shallow_resolve(self_ty);
+ let data = match object_ty.kind() {
+ ty::Dynamic(data, ..) => data,
+ ty::Infer(ty::TyVar(_)) => {
+ // If the self-type is an inference variable, then it MAY wind up
+ // being an object type, so induce an ambiguity.
+ candidate_set.mark_ambiguous();
+ return;
+ }
+ _ => return,
+ };
+ let env_predicates = data
+ .projection_bounds()
+ .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id)
+ .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
+
+ assemble_candidates_from_predicates(
+ selcx,
+ obligation,
+ obligation_trait_ref,
+ candidate_set,
+ ProjectionTyCandidate::Object,
+ env_predicates,
+ false,
+ );
+}
+
fn assemble_candidates_from_predicates<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
+ potentially_unnormalized_candidates: bool,
) {
debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
let infcx = selcx.infcx();
let is_match = same_def_id
&& infcx.probe(|_| {
- let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx);
- let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
- infcx
- .at(&obligation.cause, obligation.param_env)
- .sup(obligation_poly_trait_ref, data_poly_trait_ref)
- .map(|InferOk { obligations: _, value: () }| {
- // FIXME(#32730) -- do we need to take obligations
- // into account in any way? At the moment, no.
- })
- .is_ok()
+ selcx.match_projection_projections(
+ obligation,
+ obligation_trait_ref,
+ &data,
+ potentially_unnormalized_candidates,
+ )
});
debug!(
if is_match {
candidate_set.push_candidate(ctor(data));
+
+ if potentially_unnormalized_candidates
+ && !obligation.predicate.has_infer_types_or_consts()
+ {
+ // HACK: Pick the first trait def candidate for a fully
+ // inferred predicate. This is to allow duplicates that
+ // differ only in normalization.
+ return;
+ }
}
}
}
super::ImplSource::Closure(_)
| super::ImplSource::Generator(_)
| super::ImplSource::FnPointer(_)
- | super::ImplSource::Object(_)
| super::ImplSource::TraitAlias(_) => {
debug!("assemble_candidates_from_impls: impl_source={:?}", impl_source);
true
// in `assemble_candidates_from_param_env`.
false
}
+ super::ImplSource::Object(_) => {
+ // Handled by the `Object` projection candidate. See
+ // `assemble_candidates_from_object_ty` for an explanation of
+ // why we special case object types.
+ false
+ }
super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) => {
// These traits have no associated types.
selcx.tcx().sess.delay_span_bug(
fn confirm_candidate<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
- obligation_trait_ref: &ty::TraitRef<'tcx>,
candidate: ProjectionTyCandidate<'tcx>,
) -> Progress<'tcx> {
debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
let mut progress = match candidate {
ProjectionTyCandidate::ParamEnv(poly_projection)
- | ProjectionTyCandidate::TraitDef(poly_projection) => {
- confirm_param_env_candidate(selcx, obligation, poly_projection)
+ | ProjectionTyCandidate::Object(poly_projection) => {
+ confirm_param_env_candidate(selcx, obligation, poly_projection, false)
+ }
+
+ ProjectionTyCandidate::TraitDef(poly_projection) => {
+ confirm_param_env_candidate(selcx, obligation, poly_projection, true)
}
ProjectionTyCandidate::Select(impl_source) => {
- confirm_select_candidate(selcx, obligation, obligation_trait_ref, impl_source)
+ confirm_select_candidate(selcx, obligation, impl_source)
}
};
// When checking for cycle during evaluation, we compare predicates with
fn confirm_select_candidate<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
- obligation_trait_ref: &ty::TraitRef<'tcx>,
impl_source: Selection<'tcx>,
) -> Progress<'tcx> {
match impl_source {
super::ImplSource::DiscriminantKind(data) => {
confirm_discriminant_kind_candidate(selcx, obligation, data)
}
- super::ImplSource::Object(_) => {
- confirm_object_candidate(selcx, obligation, obligation_trait_ref)
- }
- super::ImplSource::AutoImpl(..)
+ super::ImplSource::Object(_)
+ | super::ImplSource::AutoImpl(..)
| super::ImplSource::Param(..)
| super::ImplSource::Builtin(..)
| super::ImplSource::TraitAlias(..) =>
}
}
-fn confirm_object_candidate<'cx, 'tcx>(
- selcx: &mut SelectionContext<'cx, 'tcx>,
- obligation: &ProjectionTyObligation<'tcx>,
- obligation_trait_ref: &ty::TraitRef<'tcx>,
-) -> Progress<'tcx> {
- let self_ty = obligation_trait_ref.self_ty();
- let object_ty = selcx.infcx().shallow_resolve(self_ty);
- debug!("confirm_object_candidate(object_ty={:?})", object_ty);
- let data = match object_ty.kind() {
- ty::Dynamic(data, ..) => data,
- _ => span_bug!(
- obligation.cause.span,
- "confirm_object_candidate called with non-object: {:?}",
- object_ty
- ),
- };
- let env_predicates = data
- .projection_bounds()
- .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate(selcx.tcx()));
- let env_predicate = {
- let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
-
- // select only those projections that are actually projecting an
- // item with the correct name
-
- let env_predicates = env_predicates.filter_map(|o| match o.predicate.skip_binders() {
- ty::PredicateAtom::Projection(data)
- if data.projection_ty.item_def_id == obligation.predicate.item_def_id =>
- {
- Some(ty::Binder::bind(data))
- }
- _ => None,
- });
-
- // select those with a relevant trait-ref
- let mut env_predicates = env_predicates.filter(|data| {
- let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
- let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
- selcx.infcx().probe(|_| {
- selcx
- .infcx()
- .at(&obligation.cause, obligation.param_env)
- .sup(obligation_poly_trait_ref, data_poly_trait_ref)
- .is_ok()
- })
- });
-
- // select the first matching one; there really ought to be one or
- // else the object type is not WF, since an object type should
- // include all of its projections explicitly
- match env_predicates.next() {
- Some(env_predicate) => env_predicate,
- None => {
- debug!(
- "confirm_object_candidate: no env-predicate \
- found in object type `{:?}`; ill-formed",
- object_ty
- );
- return Progress::error(selcx.tcx());
- }
- }
- };
-
- confirm_param_env_candidate(selcx, obligation, env_predicate)
-}
-
fn confirm_generator_candidate<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
}
});
- confirm_param_env_candidate(selcx, obligation, predicate)
+ confirm_param_env_candidate(selcx, obligation, predicate, false)
.with_addl_obligations(impl_source.nested)
.with_addl_obligations(obligations)
}
ty: self_ty.discriminant_ty(tcx),
};
- confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate))
+ confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false)
}
fn confirm_fn_pointer_candidate<'cx, 'tcx>(
ty: ret_type,
});
- confirm_param_env_candidate(selcx, obligation, predicate)
+ confirm_param_env_candidate(selcx, obligation, predicate, false)
}
fn confirm_param_env_candidate<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
+ potentially_unnormalized_candidate: bool,
) -> Progress<'tcx> {
let infcx = selcx.infcx();
let cause = &obligation.cause;
let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx);
let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx);
+ let mut nested_obligations = Vec::new();
+ let cache_trait_ref = if potentially_unnormalized_candidate {
+ ensure_sufficient_stack(|| {
+ normalize_with_depth_to(
+ selcx,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &cache_trait_ref,
+ &mut nested_obligations,
+ )
+ })
+ } else {
+ cache_trait_ref
+ };
+
match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) {
- Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations },
+ Ok(InferOk { value: _, obligations }) => {
+ nested_obligations.extend(obligations);
+ assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);
+ Progress { ty: cache_entry.ty, obligations: nested_obligations }
+ }
Err(e) => {
let msg = format!(
"Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
) -> Progress<'tcx> {
let tcx = selcx.tcx();
- let ImplSourceUserDefinedData { impl_def_id, substs, nested } = impl_impl_source;
+ let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
let assoc_item_id = obligation.predicate.item_def_id;
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
let ty = tcx.type_of(assoc_ty.item.def_id);
if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
let err = tcx.ty_error_with_message(
- DUMMY_SP,
+ obligation.cause.span,
"impl item and trait item have different parameter counts",
);
Progress { ty: err, obligations: nested }
} else {
+ assoc_ty_own_obligations(selcx, obligation, &mut nested);
Progress { ty: ty.subst(tcx, substs), obligations: nested }
}
}
+// Get obligations corresponding to the predicates from the where-clause of the
+// associated type itself.
+// Note: `feature(generic_associated_types)` is required to write such
+// predicates, even for non-generic associcated types.
+fn assoc_ty_own_obligations<'cx, 'tcx>(
+ selcx: &mut SelectionContext<'cx, 'tcx>,
+ obligation: &ProjectionTyObligation<'tcx>,
+ nested: &mut Vec<PredicateObligation<'tcx>>,
+) {
+ let tcx = selcx.tcx();
+ for predicate in tcx
+ .predicates_of(obligation.predicate.item_def_id)
+ .instantiate_own(tcx, obligation.predicate.substs)
+ .predicates
+ {
+ let normalized = normalize_with_depth_to(
+ selcx,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &predicate,
+ nested,
+ );
+ nested.push(Obligation::with_depth(
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation.param_env,
+ normalized,
+ ));
+ }
+}
+
/// Locate the definition of an associated type in the specialization hierarchy,
/// starting from the given impl.
///
debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
- let needs_infer = stack.obligation.predicate.needs_infer();
+ let needs_infer = stack.obligation.predicate.has_infer_types_or_consts();
// If there are STILL multiple candidates, we can further
// reduce the list by dropping duplicates -- including
.infcx
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
- if result {
- candidates.vec.push(ProjectionCandidate);
+ for predicate_index in result {
+ candidates.vec.push(ProjectionCandidate(predicate_index));
}
}
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk;
+use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness};
use rustc_span::def_id::DefId;
-use crate::traits::project::{self, normalize_with_depth};
+use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
use crate::traits::select::TraitObligationExt;
use crate::traits::util;
use crate::traits::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
Ok(ImplSource::AutoImpl(data))
}
- ProjectionCandidate => {
- self.confirm_projection_candidate(obligation);
- Ok(ImplSource::Param(Vec::new()))
+ ProjectionCandidate(idx) => {
+ let obligations = self.confirm_projection_candidate(obligation, idx);
+ Ok(ImplSource::Param(obligations))
}
ClosureCandidate => {
}
}
- fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
+ fn confirm_projection_candidate(
+ &mut self,
+ obligation: &TraitObligation<'tcx>,
+ idx: usize,
+ ) -> Vec<PredicateObligation<'tcx>> {
self.infcx.commit_unconditionally(|_| {
- let result = self.match_projection_obligation_against_definition_bounds(obligation);
- assert!(result);
+ let tcx = self.tcx();
+
+ let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
+ let placeholder_trait_predicate =
+ self.infcx().replace_bound_vars_with_placeholders(&trait_predicate);
+ let placeholder_self_ty = placeholder_trait_predicate.self_ty();
+ let (def_id, substs) = match *placeholder_self_ty.kind() {
+ ty::Projection(proj) => (proj.item_def_id, proj.substs),
+ ty::Opaque(def_id, substs) => (def_id, substs),
+ _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
+ };
+
+ let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs);
+ let candidate = candidate_predicate
+ .to_opt_poly_trait_ref()
+ .expect("projection candidate is not a trait predicate");
+ let mut obligations = Vec::new();
+ let candidate = normalize_with_depth_to(
+ self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &candidate,
+ &mut obligations,
+ );
+
+ obligations.extend(
+ self.infcx
+ .at(&obligation.cause, obligation.param_env)
+ .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate)
+ .map(|InferOk { obligations, .. }| obligations)
+ .unwrap_or_else(|_| {
+ bug!(
+ "Projection bound `{:?}` was applicable to `{:?}` but now is not",
+ candidate,
+ obligation
+ );
+ }),
+ );
+
+ if let ty::Projection(..) = placeholder_self_ty.kind() {
+ for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates {
+ let normalized = normalize_with_depth_to(
+ self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &predicate,
+ &mut obligations,
+ );
+ obligations.push(Obligation::with_depth(
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation.param_env,
+ normalized,
+ ));
+ }
+ }
+
+ obligations
})
}
let trait_obligations: Vec<PredicateObligation<'_>> =
self.infcx.commit_unconditionally(|_| {
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
- let (trait_ref, _) =
+ let trait_ref =
self.infcx.replace_bound_vars_with_placeholders(&poly_trait_ref);
let cause = obligation.derived_cause(ImplDerivedObligation);
self.impl_or_trait_obligations(
// relying on projections in the impl-trait-ref.
//
// e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
- impl_obligations.append(&mut substs.obligations);
+ substs.obligations.append(&mut impl_obligations);
- ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations }
+ ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: substs.obligations }
}
fn confirm_object_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
) -> ImplSourceObjectData<'tcx, PredicateObligation<'tcx>> {
+ let tcx = self.tcx();
debug!("confirm_object_candidate({:?})", obligation);
- // FIXME(nmatsakis) skipping binder here seems wrong -- we should
- // probably flatten the binder from the obligation and the binder
- // from the object. Have to try to make a broken test case that
- // results.
- let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
- let poly_trait_ref = match self_ty.kind() {
- ty::Dynamic(data, ..) => data
- .principal()
- .unwrap_or_else(|| {
- span_bug!(obligation.cause.span, "object candidate with no principal")
- })
- .with_self_ty(self.tcx(), self_ty),
+ let trait_predicate =
+ self.infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
+ let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
+ let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
+ let data = match self_ty.kind() {
+ ty::Dynamic(data, ..) => {
+ self.infcx
+ .replace_bound_vars_with_fresh_vars(
+ obligation.cause.span,
+ HigherRankedType,
+ data,
+ )
+ .0
+ }
_ => span_bug!(obligation.cause.span, "object candidate with non-object"),
};
+ let object_trait_ref = data
+ .principal()
+ .unwrap_or_else(|| {
+ span_bug!(obligation.cause.span, "object candidate with no principal")
+ })
+ .with_self_ty(self.tcx(), self_ty);
+
let mut upcast_trait_ref = None;
let mut nested = vec![];
let vtable_base;
{
- let tcx = self.tcx();
-
// We want to find the first supertrait in the list of
// supertraits that we can unify with, and do that
// unification. We know that there is exactly one in the list
// where we can unify, because otherwise select would have
// reported an ambiguity. (When we do find a match, also
// record it for later.)
- let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while(|&t| {
- match self.infcx.commit_if_ok(|_| self.match_poly_trait_ref(obligation, t)) {
- Ok(obligations) => {
- upcast_trait_ref = Some(t);
- nested.extend(obligations);
- false
+ let nonmatching = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref))
+ .take_while(|&t| {
+ match self.infcx.commit_if_ok(|_| {
+ self.infcx
+ .at(&obligation.cause, obligation.param_env)
+ .sup(obligation_trait_ref, t)
+ .map(|InferOk { obligations, .. }| obligations)
+ .map_err(|_| ())
+ }) {
+ Ok(obligations) => {
+ upcast_trait_ref = Some(t);
+ nested.extend(obligations);
+ false
+ }
+ Err(_) => true,
}
- Err(_) => true,
- }
- });
+ });
// Additionally, for each of the non-matching predicates that
// we pass over, we sum up the set of number of vtable
vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum();
}
- ImplSourceObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base, nested }
+ let upcast_trait_ref = upcast_trait_ref.unwrap();
+
+ // Check supertraits hold. This is so that their associated type bounds
+ // will be checked in the code below.
+ for super_trait in tcx
+ .super_predicates_of(trait_predicate.def_id())
+ .instantiate(tcx, trait_predicate.trait_ref.substs)
+ .predicates
+ .into_iter()
+ {
+ if let ty::PredicateAtom::Trait(..) = super_trait.skip_binders() {
+ let normalized_super_trait = normalize_with_depth_to(
+ self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &super_trait,
+ &mut nested,
+ );
+ nested.push(Obligation::new(
+ obligation.cause.clone(),
+ obligation.param_env.clone(),
+ normalized_super_trait,
+ ));
+ }
+ }
+
+ let assoc_types: Vec<_> = tcx
+ .associated_items(trait_predicate.def_id())
+ .in_definition_order()
+ .filter_map(
+ |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None },
+ )
+ .collect();
+
+ for assoc_type in assoc_types {
+ if !tcx.generics_of(assoc_type).params.is_empty() {
+ // FIXME(generic_associated_types) generate placeholders to
+ // extend the trait substs.
+ tcx.sess.span_fatal(
+ obligation.cause.span,
+ "generic associated types in trait objects are not supported yet",
+ );
+ }
+ // This maybe belongs in wf, but that can't (doesn't) handle
+ // higher-ranked things.
+ // Prevent, e.g., `dyn Iterator<Item = str>`.
+ for bound in self.tcx().item_bounds(assoc_type) {
+ let subst_bound = bound.subst(tcx, trait_predicate.trait_ref.substs);
+ let normalized_bound = normalize_with_depth_to(
+ self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &subst_bound,
+ &mut nested,
+ );
+ nested.push(Obligation::new(
+ obligation.cause.clone(),
+ obligation.param_env.clone(),
+ normalized_bound,
+ ));
+ }
+ }
+
+ debug!("confirm_object_candidate: nested: {:?}", nested);
+ ImplSourceObjectData { upcast_trait_ref, vtable_base, nested }
}
fn confirm_fn_pointer_candidate(
)
.map_bound(|(trait_ref, _)| trait_ref);
- let Normalized { value: trait_ref, obligations } = ensure_sufficient_stack(|| {
- project::normalize_with_depth(
+ let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| {
+ normalize_with_depth(
self,
obligation.param_env,
obligation.cause.clone(),
)
});
- self.confirm_poly_trait_refs(
+ obligations.extend(self.confirm_poly_trait_refs(
obligation.cause.clone(),
obligation.param_env,
obligation.predicate.to_poly_trait_ref(),
trait_ref,
- )?;
+ )?);
Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested: obligations })
}
debug!("confirm_trait_alias_candidate({:?}, {:?})", obligation, alias_def_id);
self.infcx.commit_unconditionally(|_| {
- let (predicate, _) =
+ let predicate =
self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
let trait_ref = predicate.trait_ref;
let trait_def_id = trait_ref.def_id;
use super::const_evaluatable;
use super::project;
use super::project::normalize_with_depth_to;
+use super::project::ProjectionTyObligation;
use super::util;
use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
use super::wf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
-use rustc_middle::ty::{
- self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
-};
+use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
+use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_span::symbol::sym;
use std::cell::{Cell, RefCell};
Err(SelectionError::Overflow)
}
Err(e) => Err(e),
- Ok(candidate) => Ok(Some(candidate)),
+ Ok(candidate) => {
+ debug!("select: candidate = {:?}", candidate);
+ Ok(Some(candidate))
+ }
}
}
predicates: I,
) -> Result<EvaluationResult, OverflowError>
where
- I: IntoIterator<Item = PredicateObligation<'tcx>>,
+ I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
{
let mut result = EvaluatedToOk;
+ debug!("evaluate_predicates_recursively({:?})", predicates);
for obligation in predicates {
let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval);
obligation: PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
debug!(
- "evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
- previous_stack.head(),
- obligation
+ "evaluate_predicate_recursively(obligation={:?}, previous_stack={:?})",
+ obligation,
+ previous_stack.head()
);
// `previous_stack` stores a `TraitObligation`, while `obligation` is
self.infcx,
obligation.param_env,
obligation.cause.body_id,
+ obligation.recursion_depth + 1,
arg,
obligation.cause.span,
) {
Some(mut obligations) => {
self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
- self.evaluate_predicates_recursively(
- previous_stack,
- obligations.into_iter(),
- )
+ self.evaluate_predicates_recursively(previous_stack, obligations)
}
None => Ok(EvaluatedToAmbig),
},
match project::poly_project_and_unify_type(self, &project_obligation) {
Ok(Ok(Some(mut subobligations))) => {
self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
- let result = self.evaluate_predicates_recursively(
- previous_stack,
- subobligations.into_iter(),
- );
+ let result = self
+ .evaluate_predicates_recursively(previous_stack, subobligations);
if let Some(key) =
ProjectionCacheKey::from_poly_projection_predicate(self, data)
{
let result = self.evaluation_probe(|this| {
let candidate = (*candidate).clone();
match this.confirm_candidate(stack.obligation, candidate) {
- Ok(selection) => this.evaluate_predicates_recursively(
- stack.list(),
- selection.nested_obligations().into_iter(),
- ),
+ Ok(selection) => {
+ debug!("evaluate_candidate: selection = {:?}", selection);
+ this.evaluate_predicates_recursively(
+ stack.list(),
+ selection.nested_obligations().into_iter(),
+ )
+ }
Err(..) => Ok(EvaluatedToErr),
}
})?;
/// to have a *lower* recursion_depth than the obligation used to create it.
/// Projection sub-obligations may be returned from the projection cache,
/// which results in obligations with an 'old' `recursion_depth`.
- /// Additionally, methods like `wf::obligations` and
- /// `InferCtxt.subtype_predicate` produce subobligations without
- /// taking in a 'parent' depth, causing the generated subobligations
- /// to have a `recursion_depth` of `0`.
+ /// Additionally, methods like `InferCtxt.subtype_predicate` produce
+ /// subobligations without taking in a 'parent' depth, causing the
+ /// generated subobligations to have a `recursion_depth` of `0`.
///
/// To ensure that obligation_depth never decreasees, we force all subobligations
/// to have at least the depth of the original obligation.
self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate);
}
+ /// Matches a predicate against the bounds of its self type.
+ ///
+ /// Given an obligation like `<T as Foo>::Bar: Baz` where the self type is
+ /// a projection, look at the bounds of `T::Bar`, see if we can find a
+ /// `Baz` bound. We return indexes into the list returned by
+ /// `tcx.item_bounds` for any applicable bounds.
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
- ) -> bool {
+ ) -> smallvec::SmallVec<[usize; 2]> {
let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
- let (placeholder_trait_predicate, _) =
+ let placeholder_trait_predicate =
self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate);
debug!(
"match_projection_obligation_against_definition_bounds: \
);
let tcx = self.infcx.tcx;
- let predicates = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
- ty::Projection(ref data) => {
- tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
- }
- ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
+ let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
+ ty::Projection(ref data) => (data.item_def_id, data.substs),
+ ty::Opaque(def_id, substs) => (def_id, substs),
_ => {
span_bug!(
obligation.cause.span,
);
}
};
+ let bounds = tcx.item_bounds(def_id).subst(tcx, substs);
+
+ // The bounds returned by `item_bounds` may contain duplicates after
+ // normalization, so try to deduplicate when possible to avoid
+ // unnecessary ambiguity.
+ let mut distinct_normalized_bounds = FxHashSet::default();
- let matching_bound = predicates.iter().find_map(|bound| {
- if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() {
- let bound = ty::Binder::bind(pred.trait_ref);
- if self.infcx.probe(|_| {
- self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref)
- }) {
- return Some(bound);
+ let matching_bounds = bounds
+ .iter()
+ .enumerate()
+ .filter_map(|(idx, bound)| {
+ if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() {
+ let bound = ty::Binder::bind(pred.trait_ref);
+ if self.infcx.probe(|_| {
+ match self.match_projection(
+ obligation,
+ bound,
+ placeholder_trait_predicate.trait_ref,
+ ) {
+ Ok(None) => true,
+ Ok(Some(normalized_trait))
+ if distinct_normalized_bounds.insert(normalized_trait) =>
+ {
+ true
+ }
+ _ => false,
+ }
+ }) {
+ return Some(idx);
+ }
}
- }
- None
- });
+ None
+ })
+ .collect();
debug!(
"match_projection_obligation_against_definition_bounds: \
- matching_bound={:?}",
- matching_bound
+ matching_bounds={:?}",
+ matching_bounds
);
- match matching_bound {
- None => false,
- Some(bound) => {
- // Repeat the successful match, if any, this time outside of a probe.
- let result =
- self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref);
-
- assert!(result);
- true
- }
- }
+ matching_bounds
}
+ /// Equates the trait in `obligation` with trait bound. If the two traits
+ /// can be equated and the normalized trait bound doesn't contain inference
+ /// variables or placeholders, the normalized bound is returned.
fn match_projection(
&mut self,
obligation: &TraitObligation<'tcx>,
trait_bound: ty::PolyTraitRef<'tcx>,
placeholder_trait_ref: ty::TraitRef<'tcx>,
- ) -> bool {
+ ) -> Result<Option<ty::PolyTraitRef<'tcx>>, ()> {
debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
+ if placeholder_trait_ref.def_id != trait_bound.def_id() {
+ // Avoid unnecessary normalization
+ return Err(());
+ }
+
+ let Normalized { value: trait_bound, obligations: _ } = ensure_sufficient_stack(|| {
+ project::normalize_with_depth(
+ self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &trait_bound,
+ )
+ });
self.infcx
.at(&obligation.cause, obligation.param_env)
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
- .is_ok()
+ .map(|InferOk { obligations: _, value: () }| {
+ // This method is called within a probe, so we can't have
+ // inference variables and placeholders escape.
+ if !trait_bound.needs_infer() && !trait_bound.has_placeholders() {
+ Some(trait_bound)
+ } else {
+ None
+ }
+ })
+ .map_err(|_| ())
}
fn evaluate_where_clause<'o>(
) -> Result<EvaluationResult, OverflowError> {
self.evaluation_probe(|this| {
match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
- Ok(obligations) => {
- this.evaluate_predicates_recursively(stack.list(), obligations.into_iter())
- }
+ Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations),
Err(()) => Ok(EvaluatedToErr),
}
})
}
+ pub(super) fn match_projection_projections(
+ &mut self,
+ obligation: &ProjectionTyObligation<'tcx>,
+ obligation_trait_ref: &ty::TraitRef<'tcx>,
+ data: &PolyProjectionPredicate<'tcx>,
+ potentially_unnormalized_candidates: bool,
+ ) -> bool {
+ let mut nested_obligations = Vec::new();
+ let projection_ty = if potentially_unnormalized_candidates {
+ ensure_sufficient_stack(|| {
+ project::normalize_with_depth_to(
+ self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &data.map_bound_ref(|data| data.projection_ty),
+ &mut nested_obligations,
+ )
+ })
+ } else {
+ data.map_bound_ref(|data| data.projection_ty)
+ };
+
+ // FIXME(generic_associated_types): Compare the whole projections
+ let data_poly_trait_ref = projection_ty.map_bound(|proj| proj.trait_ref(self.tcx()));
+ let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
+ self.infcx
+ .at(&obligation.cause, obligation.param_env)
+ .sup(obligation_poly_trait_ref, data_poly_trait_ref)
+ .map_or(false, |InferOk { obligations, value: () }| {
+ self.evaluate_predicates_recursively(
+ TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
+ nested_obligations.into_iter().chain(obligations),
+ )
+ .map_or(false, |res| res.may_apply())
+ })
+ }
+
///////////////////////////////////////////////////////////////////////////
// WINNOW
//
//
// This is a fix for #53123 and prevents winnowing from accidentally extending the
// lifetime of a variable.
- match other.candidate {
+ match (&other.candidate, &victim.candidate) {
+ (_, AutoImplCandidate(..)) | (AutoImplCandidate(..), _) => {
+ bug!(
+ "default implementations shouldn't be recorded \
+ when there are other valid candidates"
+ );
+ }
+
// (*)
- BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => true,
- ParamCandidate(ref cand) => match victim.candidate {
- AutoImplCandidate(..) => {
- bug!(
- "default implementations shouldn't be recorded \
- when there are other valid candidates"
- );
- }
- // (*)
- BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => false,
+ (BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate, _) => true,
+ (_, BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate) => false,
+
+ (ParamCandidate(..), ParamCandidate(..)) => false,
+
+ // Global bounds from the where clause should be ignored
+ // here (see issue #50825). Otherwise, we have a where
+ // clause so don't go around looking for impls.
+ // Arbitrarily give param candidates priority
+ // over projection and object candidates.
+ (
+ ParamCandidate(ref cand),
ImplCandidate(..)
| ClosureCandidate
| GeneratorCandidate
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
| BuiltinCandidate { .. }
- | TraitAliasCandidate(..) => {
- // Global bounds from the where clause should be ignored
- // here (see issue #50825). Otherwise, we have a where
- // clause so don't go around looking for impls.
- !is_global(cand)
- }
- ObjectCandidate | ProjectionCandidate => {
- // Arbitrarily give param candidates priority
- // over projection and object candidates.
- !is_global(cand)
- }
- ParamCandidate(..) => false,
- },
- ObjectCandidate | ProjectionCandidate => match victim.candidate {
- AutoImplCandidate(..) => {
- bug!(
- "default implementations shouldn't be recorded \
- when there are other valid candidates"
- );
- }
- // (*)
- BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => false,
+ | TraitAliasCandidate(..)
+ | ObjectCandidate
+ | ProjectionCandidate(_),
+ ) => !is_global(cand),
+ (ObjectCandidate | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
+ // Prefer these to a global where-clause bound
+ // (see issue #50825).
+ is_global(cand)
+ }
+ (
+ ImplCandidate(_)
+ | ClosureCandidate
+ | GeneratorCandidate
+ | FnPointerCandidate
+ | BuiltinObjectCandidate
+ | BuiltinUnsizeCandidate
+ | BuiltinCandidate { has_nested: true }
+ | TraitAliasCandidate(..),
+ ParamCandidate(ref cand),
+ ) => {
+ // Prefer these to a global where-clause bound
+ // (see issue #50825).
+ is_global(cand) && other.evaluation.must_apply_modulo_regions()
+ }
+
+ (ProjectionCandidate(i), ProjectionCandidate(j)) => {
+ // Arbitrarily pick the first candidate for backwards
+ // compatibility reasons. Don't let this affect inference.
+ i > j && !needs_infer
+ }
+ (ObjectCandidate, ObjectCandidate) => bug!("Duplicate object candidate"),
+ (ObjectCandidate, ProjectionCandidate(_))
+ | (ProjectionCandidate(_), ObjectCandidate) => {
+ bug!("Have both object and projection candidate")
+ }
+
+ // Arbitrarily give projection and object candidates priority.
+ (
+ ObjectCandidate | ProjectionCandidate(_),
ImplCandidate(..)
| ClosureCandidate
| GeneratorCandidate
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
| BuiltinCandidate { .. }
- | TraitAliasCandidate(..) => true,
- ObjectCandidate | ProjectionCandidate => {
- // Arbitrarily give param candidates priority
- // over projection and object candidates.
- true
- }
- ParamCandidate(ref cand) => is_global(cand),
- },
- ImplCandidate(other_def) => {
+ | TraitAliasCandidate(..),
+ ) => true,
+
+ (
+ ImplCandidate(..)
+ | ClosureCandidate
+ | GeneratorCandidate
+ | FnPointerCandidate
+ | BuiltinObjectCandidate
+ | BuiltinUnsizeCandidate
+ | BuiltinCandidate { .. }
+ | TraitAliasCandidate(..),
+ ObjectCandidate | ProjectionCandidate(_),
+ ) => false,
+
+ (&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
// See if we can toss out `victim` based on specialization.
// This requires us to know *for sure* that the `other` impl applies
// i.e., `EvaluatedToOk`.
if other.evaluation.must_apply_modulo_regions() {
- match victim.candidate {
- ImplCandidate(victim_def) => {
- let tcx = self.tcx();
- if tcx.specializes((other_def, victim_def)) {
- return true;
- }
- return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
- Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
- // Subtle: If the predicate we are evaluating has inference
- // variables, do *not* allow discarding candidates due to
- // marker trait impls.
- //
- // Without this restriction, we could end up accidentally
- // constrainting inference variables based on an arbitrarily
- // chosen trait impl.
- //
- // Imagine we have the following code:
- //
- // ```rust
- // #[marker] trait MyTrait {}
- // impl MyTrait for u8 {}
- // impl MyTrait for bool {}
- // ```
- //
- // And we are evaluating the predicate `<_#0t as MyTrait>`.
- //
- // During selection, we will end up with one candidate for each
- // impl of `MyTrait`. If we were to discard one impl in favor
- // of the other, we would be left with one candidate, causing
- // us to "successfully" select the predicate, unifying
- // _#0t with (for example) `u8`.
- //
- // However, we have no reason to believe that this unification
- // is correct - we've essentially just picked an arbitrary
- // *possibility* for _#0t, and required that this be the *only*
- // possibility.
- //
- // Eventually, we will either:
- // 1) Unify all inference variables in the predicate through
- // some other means (e.g. type-checking of a function). We will
- // then be in a position to drop marker trait candidates
- // without constraining inference variables (since there are
- // none left to constrin)
- // 2) Be left with some unconstrained inference variables. We
- // will then correctly report an inference error, since the
- // existence of multiple marker trait impls tells us nothing
- // about which one should actually apply.
- !needs_infer
- }
- Some(_) => true,
- None => false,
- };
- }
- ParamCandidate(ref cand) => {
- // Prefer the impl to a global where clause candidate.
- return is_global(cand);
- }
- _ => (),
+ let tcx = self.tcx();
+ if tcx.specializes((other_def, victim_def)) {
+ return true;
}
- }
-
- false
- }
- ClosureCandidate
- | GeneratorCandidate
- | FnPointerCandidate
- | BuiltinObjectCandidate
- | BuiltinUnsizeCandidate
- | BuiltinCandidate { has_nested: true } => {
- match victim.candidate {
- ParamCandidate(ref cand) => {
- // Prefer these to a global where-clause bound
- // (see issue #50825).
- is_global(cand) && other.evaluation.must_apply_modulo_regions()
- }
- _ => false,
+ return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
+ Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
+ // Subtle: If the predicate we are evaluating has inference
+ // variables, do *not* allow discarding candidates due to
+ // marker trait impls.
+ //
+ // Without this restriction, we could end up accidentally
+ // constrainting inference variables based on an arbitrarily
+ // chosen trait impl.
+ //
+ // Imagine we have the following code:
+ //
+ // ```rust
+ // #[marker] trait MyTrait {}
+ // impl MyTrait for u8 {}
+ // impl MyTrait for bool {}
+ // ```
+ //
+ // And we are evaluating the predicate `<_#0t as MyTrait>`.
+ //
+ // During selection, we will end up with one candidate for each
+ // impl of `MyTrait`. If we were to discard one impl in favor
+ // of the other, we would be left with one candidate, causing
+ // us to "successfully" select the predicate, unifying
+ // _#0t with (for example) `u8`.
+ //
+ // However, we have no reason to believe that this unification
+ // is correct - we've essentially just picked an arbitrary
+ // *possibility* for _#0t, and required that this be the *only*
+ // possibility.
+ //
+ // Eventually, we will either:
+ // 1) Unify all inference variables in the predicate through
+ // some other means (e.g. type-checking of a function). We will
+ // then be in a position to drop marker trait candidates
+ // without constraining inference variables (since there are
+ // none left to constrin)
+ // 2) Be left with some unconstrained inference variables. We
+ // will then correctly report an inference error, since the
+ // existence of multiple marker trait impls tells us nothing
+ // about which one should actually apply.
+ !needs_infer
+ }
+ Some(_) => true,
+ None => false,
+ };
+ } else {
+ false
}
}
- _ => false,
+
+ // Everything else is ambiguous
+ (
+ ImplCandidate(_)
+ | ClosureCandidate
+ | GeneratorCandidate
+ | FnPointerCandidate
+ | BuiltinObjectCandidate
+ | BuiltinUnsizeCandidate
+ | BuiltinCandidate { has_nested: true }
+ | TraitAliasCandidate(..),
+ ImplCandidate(_)
+ | ClosureCandidate
+ | GeneratorCandidate
+ | FnPointerCandidate
+ | BuiltinObjectCandidate
+ | BuiltinUnsizeCandidate
+ | BuiltinCandidate { has_nested: true }
+ | TraitAliasCandidate(..),
+ ) => false,
}
}
let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
self.infcx.commit_unconditionally(|_| {
- let (placeholder_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty);
+ let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(&ty);
let Normalized { value: normalized_ty, mut obligations } =
ensure_sufficient_stack(|| {
project::normalize_with_depth(
return Err(());
}
- let (placeholder_obligation, _) =
+ let placeholder_obligation =
self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
infcx: &InferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
+ recursion_depth: usize,
arg: GenericArg<'tcx>,
span: Span,
) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
GenericArgKind::Lifetime(..) => return Some(Vec::new()),
};
- let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
+ let mut wf =
+ WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None };
wf.compute(arg);
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out);
span: Span,
item: Option<&'tcx hir::Item<'tcx>>,
) -> Vec<traits::PredicateObligation<'tcx>> {
- let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
+ let mut wf =
+ WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item };
wf.compute_trait_ref(trait_ref, Elaborate::All);
wf.normalize()
}
predicate: ty::Predicate<'tcx>,
span: Span,
) -> Vec<traits::PredicateObligation<'tcx>> {
- let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
+ let mut wf = WfPredicates {
+ infcx,
+ param_env,
+ body_id,
+ span,
+ out: vec![],
+ recursion_depth: 0,
+ item: None,
+ };
// It's ok to skip the binder here because wf code is prepared for it
match predicate.skip_binders() {
body_id: hir::HirId,
span: Span,
out: Vec<traits::PredicateObligation<'tcx>>,
+ recursion_depth: usize,
item: Option<&'tcx hir::Item<'tcx>>,
}
traits::ObligationCause::new(self.span, self.body_id, code)
}
- fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
+ fn normalize(mut self) -> Vec<traits::PredicateObligation<'tcx>> {
let cause = self.cause(traits::MiscObligation);
let infcx = &mut self.infcx;
let param_env = self.param_env;
let mut obligations = Vec::with_capacity(self.out.len());
- for pred in &self.out {
- assert!(!pred.has_escaping_bound_vars());
+ for mut obligation in self.out {
+ assert!(!obligation.has_escaping_bound_vars());
let mut selcx = traits::SelectionContext::new(infcx);
- let i = obligations.len();
- let value =
- traits::normalize_to(&mut selcx, param_env, cause.clone(), pred, &mut obligations);
- obligations.insert(i, value);
+ // Don't normalize the whole obligation, the param env is either
+ // already normalized, or we're currently normalizing the
+ // param_env. Either way we should only normalize the predicate.
+ let normalized_predicate = traits::project::normalize_with_depth_to(
+ &mut selcx,
+ param_env,
+ cause.clone(),
+ self.recursion_depth,
+ &obligation.predicate,
+ &mut obligations,
+ );
+ obligation.predicate = normalized_predicate;
+ obligations.push(obligation);
}
obligations
}
debug!("compute_trait_ref obligations {:?}", obligations);
let cause = self.cause(traits::MiscObligation);
let param_env = self.param_env;
+ let depth = self.recursion_depth;
let item = self.item;
&obligation.predicate,
tcx.associated_items(trait_ref.def_id).in_definition_order(),
);
- traits::Obligation::new(cause, param_env, obligation.predicate)
+ traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate)
};
if let Elaborate::All = elaborate {
new_cause.make_mut().span = self_ty.span;
}
}
- traits::Obligation::new(
+ traits::Obligation::with_depth(
new_cause,
+ depth,
param_env,
ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
)
/// Pushes the obligations required for `trait_ref::Item` to be WF
/// into `self.out`.
fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
- // A projection is well-formed if (a) the trait ref itself is
- // WF and (b) the trait-ref holds. (It may also be
- // normalizable and be WF that way.)
- let trait_ref = data.trait_ref(self.infcx.tcx);
- self.compute_trait_ref(&trait_ref, Elaborate::None);
-
- if !data.has_escaping_bound_vars() {
- let predicate = trait_ref.without_const().to_predicate(self.infcx.tcx);
- let cause = self.cause(traits::ProjectionWf(data));
- self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
- }
+ // A projection is well-formed if
+ //
+ // (a) its predicates hold (*)
+ // (b) its substs are wf
+ //
+ // (*) The predicates of an associated type include the predicates of
+ // the trait that it's contained in. For example, given
+ //
+ // trait A<T>: Clone {
+ // type X where T: Copy;
+ // }
+ //
+ // The predicates of `<() as A<i32>>::X` are:
+ // [
+ // `(): Sized`
+ // `(): Clone`
+ // `(): A<i32>`
+ // `i32: Sized`
+ // `i32: Clone`
+ // `i32: Copy`
+ // ]
+ let obligations = self.nominal_obligations(data.item_def_id, data.substs);
+ self.out.extend(obligations);
+
+ let tcx = self.tcx();
+ let cause = self.cause(traits::MiscObligation);
+ let param_env = self.param_env;
+ let depth = self.recursion_depth;
+
+ self.out.extend(
+ data.substs
+ .iter()
+ .filter(|arg| {
+ matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
+ })
+ .filter(|arg| !arg.has_escaping_bound_vars())
+ .map(|arg| {
+ traits::Obligation::with_depth(
+ cause.clone(),
+ depth,
+ param_env,
+ ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
+ )
+ }),
+ );
}
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
def_id: self.infcx.tcx.require_lang_item(LangItem::Sized, None),
substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
};
- self.out.push(traits::Obligation::new(
+ self.out.push(traits::Obligation::with_depth(
cause,
+ self.recursion_depth,
self.param_env,
trait_ref.without_const().to_predicate(self.infcx.tcx),
));
fn compute(&mut self, arg: GenericArg<'tcx>) {
let mut walker = arg.walk();
let param_env = self.param_env;
+ let depth = self.recursion_depth;
while let Some(arg) = walker.next() {
let ty = match arg.unpack() {
GenericArgKind::Type(ty) => ty,
let predicate = ty::PredicateAtom::ConstEvaluatable(def, substs)
.to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
- self.out.push(traits::Obligation::new(
+ self.out.push(traits::Obligation::with_depth(
cause,
+ self.recursion_depth,
self.param_env,
predicate,
));
val: ty::ConstKind::Infer(resolved),
..*constant
});
- self.out.push(traits::Obligation::new(
+ self.out.push(traits::Obligation::with_depth(
cause,
+ self.recursion_depth,
self.param_env,
ty::PredicateAtom::WellFormed(resolved_constant.into())
.to_predicate(self.tcx()),
// WfReference
if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
- self.out.push(traits::Obligation::new(
+ self.out.push(traits::Obligation::with_depth(
cause,
+ depth,
param_env,
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(rty, r))
.to_predicate(self.tcx()),
let component_traits = data.auto_traits().chain(data.principal_def_id());
let tcx = self.tcx();
self.out.extend(component_traits.map(|did| {
- traits::Obligation::new(
+ traits::Obligation::with_depth(
cause.clone(),
+ depth,
param_env,
ty::PredicateAtom::ObjectSafe(did).to_predicate(tcx),
)
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
// Not yet resolved, but we've made progress.
let cause = self.cause(traits::MiscObligation);
- self.out.push(traits::Obligation::new(
+ self.out.push(traits::Obligation::with_depth(
cause,
+ self.recursion_depth,
param_env,
ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()),
));
.zip(origins.into_iter().rev())
.map(|((pred, span), origin_def_id)| {
let cause = self.cause(traits::BindingObligation(origin_def_id, span));
- traits::Obligation::new(cause, self.param_env, pred)
+ traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
})
.filter(|pred| !pred.has_escaping_bound_vars())
.collect()
let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
let outlives =
ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
- self.out.push(traits::Obligation::new(
+ self.out.push(traits::Obligation::with_depth(
cause,
+ self.recursion_depth,
self.param_env,
outlives.to_predicate(self.infcx.tcx),
));
.map(|wc| wc.fold_with(&mut regions_substitutor))
.filter_map(|wc| LowerInto::<Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>>::lower_into(wc, &self.interner)).collect()
}
+
+ fn bounds_for<T>(&self, def_id: DefId, bound_vars: SubstsRef<'tcx>) -> Vec<T>
+ where
+ ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option<T>>,
+ {
+ self.interner
+ .tcx
+ .explicit_item_bounds(def_id)
+ .iter()
+ .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars))
+ .filter_map(|bound| LowerInto::<Option<_>>::lower_into(bound, &self.interner))
+ .collect()
+ }
}
impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'tcx> {
}
let bound_vars = bound_vars_for_item(self.interner.tcx, def_id);
let binders = binders_for(&self.interner, bound_vars);
- // FIXME(chalk): this really isn't right I don't think. The functions
- // for GATs are a bit hard to figure out. Are these supposed to be where
- // clauses or bounds?
+
let where_clauses = self.where_clauses_for(def_id, bound_vars);
+ let bounds = self.bounds_for(def_id, bound_vars);
Arc::new(chalk_solve::rust_ir::AssociatedTyDatum {
trait_id: chalk_ir::TraitId(trait_def_id),
name: (),
binders: chalk_ir::Binders::new(
binders,
- chalk_solve::rust_ir::AssociatedTyDatumBound { bounds: vec![], where_clauses },
+ chalk_solve::rust_ir::AssociatedTyDatumBound { bounds, where_clauses },
),
})
}
let bound_vars = bound_vars_for_item(self.interner.tcx, opaque_ty_id.0);
let binders = binders_for(&self.interner, bound_vars);
let where_clauses = self.where_clauses_for(opaque_ty_id.0, bound_vars);
+ let bounds = self.bounds_for(opaque_ty_id.0, bound_vars);
let value = chalk_solve::rust_ir::OpaqueTyDatumBound {
- bounds: chalk_ir::Binders::new(binders.clone(), vec![]),
+ bounds: chalk_ir::Binders::new(binders.clone(), bounds),
where_clauses: chalk_ir::Binders::new(binders, where_clauses),
};
+
Arc::new(chalk_solve::rust_ir::OpaqueTyDatum {
opaque_ty_id,
bound: chalk_ir::Binders::empty(&self.interner, value),
}
}
+// We lower into an Option here since there are some predicates which Chalk
+// doesn't have a representation for yet (as an `InlineBound`). The `Option` will
+// eventually be removed.
+impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<RustInterner<'tcx>>>>
+ for ty::Predicate<'tcx>
+{
+ fn lower_into(
+ self,
+ interner: &RustInterner<'tcx>,
+ ) -> Option<chalk_solve::rust_ir::QuantifiedInlineBound<RustInterner<'tcx>>> {
+ match self.bound_atom(interner.tcx).skip_binder() {
+ ty::PredicateAtom::Trait(predicate, _) => {
+ let (predicate, binders, _named_regions) =
+ collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate));
+
+ Some(chalk_ir::Binders::new(
+ binders,
+ chalk_solve::rust_ir::InlineBound::TraitBound(
+ predicate.trait_ref.lower_into(interner),
+ ),
+ ))
+ }
+ ty::PredicateAtom::Projection(predicate) => {
+ let (predicate, binders, _named_regions) =
+ collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate));
+
+ Some(chalk_ir::Binders::new(
+ binders,
+ chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)),
+ ))
+ }
+ ty::PredicateAtom::TypeOutlives(_predicate) => None,
+ ty::PredicateAtom::WellFormed(_ty) => None,
+
+ ty::PredicateAtom::RegionOutlives(..)
+ | ty::PredicateAtom::ObjectSafe(..)
+ | ty::PredicateAtom::ClosureKind(..)
+ | ty::PredicateAtom::Subtype(..)
+ | ty::PredicateAtom::ConstEvaluatable(..)
+ | ty::PredicateAtom::ConstEquate(..)
+ | ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+ bug!("unexpected predicate {}", &self)
+ }
+ }
+ }
+}
+
+impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound<RustInterner<'tcx>>>
+ for ty::TraitRef<'tcx>
+{
+ fn lower_into(
+ self,
+ interner: &RustInterner<'tcx>,
+ ) -> chalk_solve::rust_ir::TraitBound<RustInterner<'tcx>> {
+ chalk_solve::rust_ir::TraitBound {
+ trait_id: chalk_ir::TraitId(self.def_id),
+ args_no_self: self.substs[1..].iter().map(|arg| arg.lower_into(interner)).collect(),
+ }
+ }
+}
+
+impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>>>
+ for ty::ProjectionPredicate<'tcx>
+{
+ fn lower_into(
+ self,
+ interner: &RustInterner<'tcx>,
+ ) -> chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>> {
+ let trait_ref = self.projection_ty.trait_ref(interner.tcx);
+ chalk_solve::rust_ir::AliasEqBound {
+ trait_bound: trait_ref.lower_into(interner),
+ associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
+ parameters: self.projection_ty.substs[trait_ref.substs.len()..]
+ .iter()
+ .map(|arg| arg.lower_into(interner))
+ .collect(),
+ value: self.ty.lower_into(interner),
+ }
+ }
+}
+
/// To collect bound vars, we have to do two passes. In the first pass, we
/// collect all `BoundRegion`s and `ty::Bound`s. In the second pass, we then
/// replace `BrNamed` into `BrAnon`. The two separate passes are important,
// than the ultimate set. (Note: normally there won't be
// unresolved inference variables here anyway, but there might be
// during typeck under some circumstances.)
- let obligations =
- wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, arg, DUMMY_SP).unwrap_or(vec![]);
+ let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
+ .unwrap_or(vec![]);
// N.B., all of these predicates *ought* to be easily proven
// true. In fact, their correctness is (mostly) implied by
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::svh::Svh;
use rustc_hir as hir;
-use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_infer::traits::util;
use rustc_middle::hir::map as hir_map;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{
self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
};
fn_like.asyncness()
}
-/// For associated types we allow bounds written on the associated type
-/// (`type X: Trait`) to be used as candidates. We also allow the same bounds
-/// when desugared as bounds on the trait `where Self::X: Trait`.
-///
-/// Note that this filtering is done with the items identity substs to
-/// simplify checking that these bounds are met in impls. This means that
-/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
-/// `hr-associated-type-bound-1.rs`.
-fn associated_type_projection_predicates(
- tcx: TyCtxt<'_>,
- assoc_item_def_id: DefId,
-) -> &'_ ty::List<ty::Predicate<'_>> {
- let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id);
- // We include predicates from the trait as well to handle
- // `where Self::X: Trait`.
- let item_bounds = generic_trait_bounds.instantiate_identity(tcx);
- let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter());
-
- let assoc_item_ty = ty::ProjectionTy {
- item_def_id: assoc_item_def_id,
- substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
- };
-
- let predicates = item_predicates.filter_map(|obligation| {
- let pred = obligation.predicate;
- match pred.skip_binders() {
- ty::PredicateAtom::Trait(tr, _) => {
- if let ty::Projection(p) = *tr.self_ty().kind() {
- if p == assoc_item_ty {
- return Some(pred);
- }
- }
- }
- ty::PredicateAtom::Projection(proj) => {
- if let ty::Projection(p) = *proj.projection_ty.self_ty().kind() {
- if p == assoc_item_ty {
- return Some(pred);
- }
- }
- }
- ty::PredicateAtom::TypeOutlives(outlives) => {
- if let ty::Projection(p) = *outlives.0.kind() {
- if p == assoc_item_ty {
- return Some(pred);
- }
- }
- }
- _ => {}
- }
- None
- });
-
- let result = tcx.mk_predicates(predicates);
- debug!(
- "associated_type_projection_predicates({}) = {:?}",
- tcx.def_path_str(assoc_item_def_id),
- result
- );
- result
-}
-
-/// Opaque types don't have the same issues as associated types: the only
-/// predicates on an opaque type (excluding those it inherits from its parent
-/// item) should be of the form we're expecting.
-fn opaque_type_projection_predicates(
- tcx: TyCtxt<'_>,
- def_id: DefId,
-) -> &'_ ty::List<ty::Predicate<'_>> {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
-
- let bounds = tcx.predicates_of(def_id);
- let predicates =
- util::elaborate_predicates(tcx, bounds.predicates.iter().map(|&(pred, _)| pred));
-
- let filtered_predicates = predicates.filter_map(|obligation| {
- let pred = obligation.predicate;
- match pred.skip_binders() {
- ty::PredicateAtom::Trait(tr, _) => {
- if let ty::Opaque(opaque_def_id, opaque_substs) = *tr.self_ty().kind() {
- if opaque_def_id == def_id && opaque_substs == substs {
- return Some(pred);
- }
- }
- }
- ty::PredicateAtom::Projection(proj) => {
- if let ty::Opaque(opaque_def_id, opaque_substs) =
- *proj.projection_ty.self_ty().kind()
- {
- if opaque_def_id == def_id && opaque_substs == substs {
- return Some(pred);
- }
- }
- }
- ty::PredicateAtom::TypeOutlives(outlives) => {
- if let ty::Opaque(opaque_def_id, opaque_substs) = *outlives.0.kind() {
- if opaque_def_id == def_id && opaque_substs == substs {
- return Some(pred);
- }
- } else {
- // These can come from elaborating other predicates
- return None;
- }
- }
- // These can come from elaborating other predicates
- ty::PredicateAtom::RegionOutlives(_) => return None,
- _ => {}
- }
- tcx.sess.delay_span_bug(
- obligation.cause.span(tcx),
- &format!("unexpected predicate {:?} on opaque type", pred),
- );
- None
- });
-
- let result = tcx.mk_predicates(filtered_predicates);
- debug!("opaque_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result);
- result
-}
-
-fn projection_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
- match tcx.def_kind(def_id) {
- DefKind::AssocTy => associated_type_projection_predicates(tcx, def_id),
- DefKind::OpaqueTy => opaque_type_projection_predicates(tcx, def_id),
- k => bug!("projection_predicates called on {}", k.descr(def_id)),
- }
-}
-
pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers {
asyncness,
instance_def_size_estimate,
issue33140_self_ty,
impl_defaultness,
- projection_predicates,
..*providers
};
}
self.region_bounds
.iter()
.map(|&(region_bound, span)| {
- // Account for the binder being introduced below; no need to shift `param_ty`
- // because, at present at least, it either only refers to early-bound regions,
- // or it's a generic associated type that deliberately has escaping bound vars.
- let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
let outlives = ty::OutlivesPredicate(param_ty, region_bound);
- (ty::Binder::bind(outlives).to_predicate(tcx), span)
+ (ty::Binder::dummy(outlives).to_predicate(tcx), span)
})
.chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
use super::coercion::CoerceMany;
+use super::compare_method::check_type_bounds;
use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
use super::*;
use rustc_attr as attr;
-use rustc_errors::Applicability;
+use rustc_errors::{Applicability, ErrorReported};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ItemKind, Node};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::RegionVariableOrigin;
+use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt, Representability};
use rustc_span::symbol::sym;
use rustc_span::{self, MultiSpan, Span};
use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::opaque_types::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCauseCode};
pub fn check_wf_new(tcx: TyCtxt<'_>) {
origin: &hir::OpaqueTyOrigin,
) {
check_opaque_for_inheriting_lifetimes(tcx, def_id, span);
- tcx.ensure().type_of(def_id);
- check_opaque_for_cycles(tcx, def_id, substs, span, origin);
+ if tcx.type_of(def_id).references_error() {
+ return;
+ }
+ if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() {
+ return;
+ }
+ check_opaque_meets_bounds(tcx, def_id, substs, span, origin);
}
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
ty: None,
};
let prohibit_opaque = tcx
- .predicates_of(def_id)
- .predicates
+ .explicit_item_bounds(def_id)
.iter()
.any(|(predicate, _)| predicate.visit_with(&mut visitor));
debug!(
span,
E0760,
"`{}` return type cannot contain a projection or `Self` that references lifetimes from \
- a parent scope",
+ a parent scope",
if is_async { "async fn" } else { "impl Trait" },
);
substs: SubstsRef<'tcx>,
span: Span,
origin: &hir::OpaqueTyOrigin,
-) {
+) -> Result<(), ErrorReported> {
if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs)
{
match origin {
}
_ => opaque_type_cycle_error(tcx, def_id, span),
}
+ Err(ErrorReported)
+ } else {
+ Ok(())
}
}
+/// Check that the concrete type behind `impl Trait` actually implements `Trait`.
+///
+/// This is mostly checked at the places that specify the opaque type, but we
+/// check those cases in the `param_env` of that function, which may have
+/// bounds not on this opaque type:
+///
+/// type X<T> = impl Clone
+/// fn f<T: Clone>(t: T) -> X<T> {
+/// t
+/// }
+///
+/// Without this check the above code is incorrectly accepted: we would ICE if
+/// some tried, for example, to clone an `Option<X<&mut ()>>`.
+fn check_opaque_meets_bounds<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+ substs: SubstsRef<'tcx>,
+ span: Span,
+ origin: &hir::OpaqueTyOrigin,
+) {
+ match origin {
+ // Checked when type checking the function containing them.
+ hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return,
+ // Can have different predicates to their defining use
+ hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => {}
+ }
+
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let param_env = tcx.param_env(def_id);
+
+ tcx.infer_ctxt().enter(move |infcx| {
+ let inh = Inherited::new(infcx, def_id);
+ let infcx = &inh.infcx;
+ let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
+
+ let misc_cause = traits::ObligationCause::misc(span, hir_id);
+
+ let (_, opaque_type_map) = inh.register_infer_ok_obligations(
+ infcx.instantiate_opaque_types(def_id, hir_id, param_env, &opaque_ty, span),
+ );
+
+ for (def_id, opaque_defn) in opaque_type_map {
+ match infcx
+ .at(&misc_cause, param_env)
+ .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, opaque_defn.substs))
+ {
+ Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
+ Err(ty_err) => tcx.sess.delay_span_bug(
+ opaque_defn.definition_span,
+ &format!(
+ "could not unify `{}` with revealed type:\n{}",
+ opaque_defn.concrete_ty, ty_err,
+ ),
+ ),
+ }
+ }
+
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
+ infcx.report_fulfillment_errors(errors, None, false);
+ }
+
+ // Finally, resolve all regions. This catches wily misuses of
+ // lifetime parameters.
+ let fcx = FnCtxt::new(&inh, param_env, hir_id);
+ fcx.regionck_item(hir_id, span, &[]);
+ });
+}
+
pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
debug!(
"check_item_type(it.hir_id={}, it.name={})",
for item in items.iter() {
let item = tcx.hir().trait_item(item.id);
- if let hir::TraitItemKind::Fn(sig, _) = &item.kind {
- let abi = sig.header.abi;
- fn_maybe_err(tcx, item.ident.span, abi);
+ match item.kind {
+ hir::TraitItemKind::Fn(ref sig, _) => {
+ let abi = sig.header.abi;
+ fn_maybe_err(tcx, item.ident.span, abi);
+ }
+ hir::TraitItemKind::Type(.., Some(_default)) => {
+ let item_def_id = tcx.hir().local_def_id(item.hir_id).to_def_id();
+ let assoc_item = tcx.associated_item(item_def_id);
+ let trait_substs =
+ InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ let _: Result<_, rustc_errors::ErrorReported> = check_type_bounds(
+ tcx,
+ assoc_item,
+ assoc_item,
+ item.span,
+ ty::TraitRef { def_id: def_id.to_def_id(), substs: trait_substs },
+ );
+ }
+ _ => {}
}
}
}
use rustc_hir::intravisit;
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
+use rustc_infer::traits::util;
use rustc_middle::ty;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::subst::{InternalSubsts, Subst};
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id);
- fcx.regionck_item(impl_m_hir_id, impl_m_span, &[]);
+ fcx.regionck_item(impl_m_hir_id, impl_m_span, trait_sig.inputs_and_output);
Ok(())
})
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
- compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
+ check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
})();
}
/// For default associated types the normalization is not possible (the value
/// from the impl could be overridden). We also can't normalize generic
/// associated types (yet) because they contain bound parameters.
-fn compare_projection_bounds<'tcx>(
+pub fn check_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ty: &ty::AssocItem,
impl_ty: &ty::AssocItem,
impl_ty_span: Span,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorReported> {
- let have_gats = tcx.features().generic_associated_types;
- if impl_ty.defaultness.is_final() && !have_gats {
- // For "final", non-generic associate type implementations, we
- // don't need this as described above.
- return Ok(());
- }
-
// Given
//
// impl<A, B> Foo<u32> for (A, B) {
// ParamEnv for normalization specifically.
let normalize_param_env = {
let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
- predicates.push(
- ty::Binder::dummy(ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- item_def_id: trait_ty.def_id,
- substs: rebased_substs,
- },
- ty: impl_ty_value,
- })
- .to_predicate(tcx),
- );
+ match impl_ty_value.kind() {
+ ty::Projection(proj)
+ if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs =>
+ {
+ // Don't include this predicate if the projected type is
+ // exactly the same as the projection. This can occur in
+ // (somewhat dubious) code like this:
+ //
+ // impl<T> X for T where T: X { type Y = <T as X>::Y; }
+ }
+ _ => predicates.push(
+ ty::Binder::dummy(ty::ProjectionPredicate {
+ projection_ty: ty::ProjectionTy {
+ item_def_id: trait_ty.def_id,
+ substs: rebased_substs,
+ },
+ ty: impl_ty_value,
+ })
+ .to_predicate(tcx),
+ ),
+ };
ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing)
};
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
- let cause = ObligationCause::new(
- impl_ty_span,
- impl_ty_hir_id,
- ObligationCauseCode::ItemObligation(trait_ty.def_id),
- );
+ let mk_cause = |span| {
+ ObligationCause::new(
+ impl_ty_span,
+ impl_ty_hir_id,
+ ObligationCauseCode::BindingObligation(trait_ty.def_id, span),
+ )
+ };
- let predicates = tcx.projection_predicates(trait_ty.def_id);
- debug!("compare_projection_bounds: projection_predicates={:?}", predicates);
+ let obligations = tcx
+ .explicit_item_bounds(trait_ty.def_id)
+ .iter()
+ .map(|&(bound, span)| {
+ let concrete_ty_bound = bound.subst(tcx, rebased_substs);
+ debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
- for predicate in predicates {
- let concrete_ty_predicate = predicate.subst(tcx, rebased_substs);
- debug!("compare_projection_bounds: concrete predicate = {:?}", concrete_ty_predicate);
+ traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
+ })
+ .collect();
+ debug!("check_type_bounds: item_bounds={:?}", obligations);
+ for mut obligation in util::elaborate_obligations(tcx, obligations) {
let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
&mut selcx,
normalize_param_env,
normalize_cause.clone(),
- &concrete_ty_predicate,
+ &obligation.predicate,
);
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
+ obligation.predicate = normalized_predicate;
inh.register_predicates(obligations);
- inh.register_predicate(traits::Obligation::new(
- cause.clone(),
- param_env,
- normalized_predicate,
- ));
+ inh.register_predicate(obligation);
}
// Check that all obligations are satisfied by the implementation's
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
- fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
+ let implied_bounds = match impl_ty.container {
+ ty::TraitContainer(_) => vec![],
+ ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span),
+ };
+ fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &implied_bounds);
Ok(())
})
check_method_receiver(fcx, hir_sig, &item, self_ty);
}
ty::AssocKind::Type => {
+ if let ty::AssocItemContainer::TraitContainer(_) = item.container {
+ check_associated_type_bounds(fcx, item, span)
+ }
if item.defaultness.has_value() {
let ty = fcx.tcx.type_of(item.def_id);
let ty = fcx.normalize_associated_types_in(span, &ty);
for_item(tcx, item).with_fcx(|fcx, _| {
check_where_clauses(tcx, fcx, item.span, trait_def_id.to_def_id(), None);
- check_associated_type_defaults(fcx, trait_def_id.to_def_id());
vec![]
});
///
/// Assuming the defaults are used, check that all predicates (bounds on the
/// assoc type and where clauses on the trait) hold.
-fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) {
+fn check_associated_type_bounds(fcx: &FnCtxt<'_, '_>, item: &ty::AssocItem, span: Span) {
let tcx = fcx.tcx;
- let substs = InternalSubsts::identity_for_item(tcx, trait_def_id);
-
- // For all assoc. types with defaults, build a map from
- // `<Self as Trait<...>>::Assoc` to the default type.
- let map = tcx
- .associated_items(trait_def_id)
- .in_definition_order()
- .filter_map(|item| {
- if item.kind == ty::AssocKind::Type && item.defaultness.has_value() {
- // `<Self as Trait<...>>::Assoc`
- let proj = ty::ProjectionTy { substs, item_def_id: item.def_id };
- let default_ty = tcx.type_of(item.def_id);
- debug!("assoc. type default mapping: {} -> {}", proj, default_ty);
- Some((proj, default_ty))
- } else {
- None
- }
- })
- .collect::<FxHashMap<_, _>>();
-
- /// Replaces projections of associated types with their default types.
- ///
- /// This does a "shallow substitution", meaning that defaults that refer to
- /// other defaulted assoc. types will still refer to the projection
- /// afterwards, not to the other default. For example:
- ///
- /// ```compile_fail
- /// trait Tr {
- /// type A: Clone = Vec<Self::B>;
- /// type B = u8;
- /// }
- /// ```
- ///
- /// This will end up replacing the bound `Self::A: Clone` with
- /// `Vec<Self::B>: Clone`, not with `Vec<u8>: Clone`. If we did a deep
- /// substitution and ended up with the latter, the trait would be accepted.
- /// If an `impl` then replaced `B` with something that isn't `Clone`,
- /// suddenly the default for `A` is no longer valid. The shallow
- /// substitution forces the trait to add a `B: Clone` bound to be accepted,
- /// which means that an `impl` can replace any default without breaking
- /// others.
- ///
- /// Note that this isn't needed for soundness: The defaults would still be
- /// checked in any impl that doesn't override them.
- struct DefaultNormalizer<'tcx> {
- tcx: TyCtxt<'tcx>,
- map: FxHashMap<ty::ProjectionTy<'tcx>, Ty<'tcx>>,
- }
- impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
- self.tcx
- }
+ let bounds = tcx.explicit_item_bounds(item.def_id);
- fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- match t.kind() {
- ty::Projection(proj_ty) => {
- if let Some(default) = self.map.get(&proj_ty) {
- default
- } else {
- t.super_fold_with(self)
- }
- }
- _ => t.super_fold_with(self),
- }
- }
- }
-
- // Now take all predicates defined on the trait, replace any mention of
- // the assoc. types with their default, and prove them.
- // We only consider predicates that directly mention the assoc. type.
- let mut norm = DefaultNormalizer { tcx, map };
- let predicates = fcx.tcx.predicates_of(trait_def_id);
- for &(orig_pred, span) in predicates.predicates.iter() {
- let pred = orig_pred.fold_with(&mut norm);
- if pred != orig_pred {
- // Mentions one of the defaulted assoc. types
- debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred);
- let pred = fcx.normalize_associated_types_in(span, &pred);
- let cause = traits::ObligationCause::new(
- span,
- fcx.body_id,
- traits::ItemObligation(trait_def_id),
- );
- let obligation = traits::Obligation::new(cause, fcx.param_env, pred);
+ debug!("check_associated_type_bounds: bounds={:?}", bounds);
+ let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
+ let normalized_bound = fcx.normalize_associated_types_in(span, &bound);
+ traits::wf::predicate_obligations(
+ fcx,
+ fcx.param_env,
+ fcx.body_id,
+ normalized_bound,
+ bound_span,
+ )
+ });
- fcx.register_predicate(obligation);
- }
+ for obligation in wf_obligations {
+ debug!("next obligation cause: {:?}", obligation.cause);
+ fcx.register_predicate(obligation);
}
}
.collect()
}
- fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
+ pub(super) fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
match self.tcx.impl_trait_ref(impl_def_id) {
Some(ref trait_ref) => {
// Trait impl: take implied bounds from all types that
use rustc_target::spec::abi;
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
+mod item_bounds;
mod type_of;
struct OnlySelfBounds(bool);
*providers = Providers {
opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of,
+ item_bounds: item_bounds::item_bounds,
+ explicit_item_bounds: item_bounds::explicit_item_bounds,
generics_of,
predicates_of,
predicates_defined_on,
projection_ty_from_predicates,
explicit_predicates_of,
super_predicates_of,
+ trait_explicit_predicates_and_bounds,
type_param_predicates,
trait_def,
adt_def,
hir::ItemKind::OpaqueTy(..) => {
tcx.ensure().generics_of(def_id);
tcx.ensure().predicates_of(def_id);
+ tcx.ensure().explicit_item_bounds(def_id);
}
hir::ItemKind::TyAlias(..)
| hir::ItemKind::Static(..)
tcx.ensure().generics_of(def_id);
tcx.ensure().type_of(def_id);
tcx.ensure().predicates_of(def_id);
- if let hir::ItemKind::Fn(..) = it.kind {
- tcx.ensure().fn_sig(def_id);
+ match it.kind {
+ hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id),
+ hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id),
+ _ => (),
}
}
}
tcx.ensure().type_of(def_id);
}
- hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(_, Some(_)) => {
+ hir::TraitItemKind::Const(..) => {
tcx.ensure().type_of(def_id);
- // Account for `const C: _;` and `type T = _;`.
+ // Account for `const C: _;`.
+ let mut visitor = PlaceholderHirTyCollector::default();
+ visitor.visit_trait_item(trait_item);
+ placeholder_type_error(tcx, None, &[], visitor.0, false);
+ }
+
+ hir::TraitItemKind::Type(_, Some(_)) => {
+ tcx.ensure().item_bounds(def_id);
+ tcx.ensure().type_of(def_id);
+ // Account for `type T = _;`.
let mut visitor = PlaceholderHirTyCollector::default();
visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, None, &[], visitor.0, false);
}
hir::TraitItemKind::Type(_, None) => {
+ tcx.ensure().item_bounds(def_id);
// #74612: Visit and try to find bad placeholders
// even if there is no concrete type.
let mut visitor = PlaceholderHirTyCollector::default();
/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
/// N.B., this does not include any implied/inferred constraints.
-fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
+fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
debug!("explicit_predicates_of(def_id={:?})", def_id);
let mut is_trait = None;
let mut is_default_impl_trait = None;
- let mut is_trait_associated_type = None;
let icx = ItemCtxt::new(tcx, def_id);
let constness = icx.default_constness_for_trait_bounds();
let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
let ast_generics = match node {
- Node::TraitItem(item) => {
- if let hir::TraitItemKind::Type(bounds, _) = item.kind {
- is_trait_associated_type = Some((bounds, item.span));
- }
- &item.generics
- }
+ Node::TraitItem(item) => &item.generics,
Node::ImplItem(item) => &item.generics,
| ItemKind::Struct(_, ref generics)
| ItemKind::Union(_, ref generics) => generics,
- ItemKind::Trait(_, _, ref generics, .., items) => {
- is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
+ ItemKind::Trait(_, _, ref generics, ..) => {
+ is_trait = Some(ty::TraitRef::identity(tcx, def_id));
generics
}
ItemKind::TraitAlias(ref generics, _) => {
- is_trait = Some((ty::TraitRef::identity(tcx, def_id), &[]));
+ is_trait = Some(ty::TraitRef::identity(tcx, def_id));
generics
}
ItemKind::OpaqueTy(OpaqueTy {
- ref bounds,
+ bounds: _,
impl_trait_fn,
ref generics,
origin: _,
}) => {
- let bounds_predicates = ty::print::with_no_queries(|| {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- let opaque_ty = tcx.mk_opaque(def_id, substs);
-
- // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
- let bounds = AstConv::compute_bounds(
- &icx,
- opaque_ty,
- bounds,
- SizedByDefault::Yes,
- tcx.def_span(def_id),
- );
-
- bounds.predicates(tcx, opaque_ty)
- });
if impl_trait_fn.is_some() {
- // opaque types
- return ty::GenericPredicates {
- parent: None,
- predicates: tcx.arena.alloc_from_iter(bounds_predicates),
- };
+ // return-position impl trait
+ //
+ // We don't inherit predicates from the parent here:
+ // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}`
+ // then the return type is `f::<'static, T>::{{opaque}}`.
+ //
+ // If we inherited the predicates of `f` then we would
+ // require that `T: 'static` to show that the return
+ // type is well-formed.
+ //
+ // The only way to have something with this opaque type
+ // is from the return type of the containing function,
+ // which will ensure that the function's predicates
+ // hold.
+ return ty::GenericPredicates { parent: None, predicates: &[] };
} else {
- // named opaque types
- predicates.extend(bounds_predicates);
+ // type-alias impl trait
generics
}
}
// and the explicit where-clauses, but to get the full set of predicates
// on a trait we need to add in the supertrait bounds and bounds found on
// associated types.
- if let Some((_trait_ref, _)) = is_trait {
+ if let Some(_trait_ref) = is_trait {
predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
}
}
}
- // Add predicates from associated type bounds (`type X: Bound`)
- if tcx.features().generic_associated_types {
- // New behavior: bounds declared on associate type are predicates of that
- // associated type. Not the default because it needs more testing.
- if let Some((bounds, span)) = is_trait_associated_type {
- let projection_ty =
- tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id));
-
- predicates.extend(associated_item_bounds(tcx, def_id, bounds, projection_ty, span))
- }
- } else if let Some((self_trait_ref, trait_items)) = is_trait {
- // Current behavior: bounds declared on associate type are predicates
- // of its parent trait.
- predicates.extend(trait_items.iter().flat_map(|trait_item_ref| {
- trait_associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref)
- }))
- }
-
if tcx.features().const_evaluatable_checked {
predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
}
collector.preds
}
+fn trait_explicit_predicates_and_bounds(
+ tcx: TyCtxt<'_>,
+ def_id: LocalDefId,
+) -> ty::GenericPredicates<'_> {
+ assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
+ gather_explicit_predicates_of(tcx, def_id.to_def_id())
+}
+
+fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
+ if let DefKind::Trait = tcx.def_kind(def_id) {
+ // Remove bounds on associated types from the predicates, they will be
+ // returned by `explicit_item_bounds`.
+ let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
+ let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+
+ let is_assoc_item_ty = |ty: Ty<'_>| {
+ // For a predicate from a where clause to become a bound on an
+ // associated type:
+ // * It must use the identity substs of the item.
+ // * Since any generic parameters on the item are not in scope,
+ // this means that the item is not a GAT, and its identity
+ // substs are the same as the trait's.
+ // * It must be an associated type for this trait (*not* a
+ // supertrait).
+ if let ty::Projection(projection) = ty.kind() {
+ if projection.substs == trait_identity_substs
+ && tcx.associated_item(projection.item_def_id).container.id() == def_id
+ {
+ true
+ } else {
+ false
+ }
+ } else {
+ false
+ }
+ };
+
+ let predicates: Vec<_> = predicates_and_bounds
+ .predicates
+ .iter()
+ .copied()
+ .filter(|(pred, _)| match pred.skip_binders() {
+ ty::PredicateAtom::Trait(tr, _) => !is_assoc_item_ty(tr.self_ty()),
+ ty::PredicateAtom::Projection(proj) => {
+ !is_assoc_item_ty(proj.projection_ty.self_ty())
+ }
+ ty::PredicateAtom::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
+ _ => true,
+ })
+ .collect();
+ if predicates.len() == predicates_and_bounds.predicates.len() {
+ predicates_and_bounds
+ } else {
+ ty::GenericPredicates {
+ parent: predicates_and_bounds.parent,
+ predicates: tcx.arena.alloc_slice(&predicates),
+ }
+ }
+ } else {
+ gather_explicit_predicates_of(tcx, def_id)
+ }
+}
+
fn projection_ty_from_predicates(
tcx: TyCtxt<'tcx>,
key: (
projection_ty
}
-fn trait_associated_item_predicates(
- tcx: TyCtxt<'tcx>,
- def_id: DefId,
- self_trait_ref: ty::TraitRef<'tcx>,
- trait_item_ref: &hir::TraitItemRef,
-) -> Vec<(ty::Predicate<'tcx>, Span)> {
- let trait_item = tcx.hir().trait_item(trait_item_ref.id);
- let item_def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
- let bounds = match trait_item.kind {
- hir::TraitItemKind::Type(ref bounds, _) => bounds,
- _ => return Vec::new(),
- };
-
- if !tcx.generics_of(item_def_id).params.is_empty() {
- // For GATs the substs provided to the mk_projection call below are
- // wrong. We should emit a feature gate error if we get here so skip
- // this type.
- tcx.sess.delay_span_bug(trait_item.span, "gats used without feature gate");
- return Vec::new();
- }
-
- let assoc_ty = tcx.mk_projection(
- tcx.hir().local_def_id(trait_item.hir_id).to_def_id(),
- self_trait_ref.substs,
- );
-
- associated_item_bounds(tcx, def_id, bounds, assoc_ty, trait_item.span)
-}
-
-fn associated_item_bounds(
- tcx: TyCtxt<'tcx>,
- def_id: DefId,
- bounds: &'tcx [hir::GenericBound<'tcx>],
- projection_ty: Ty<'tcx>,
- span: Span,
-) -> Vec<(ty::Predicate<'tcx>, Span)> {
- let bounds = AstConv::compute_bounds(
- &ItemCtxt::new(tcx, def_id),
- projection_ty,
- bounds,
- SizedByDefault::Yes,
- span,
- );
-
- let predicates = bounds.predicates(tcx, projection_ty);
-
- predicates
-}
-
/// Converts a specific `GenericBound` from the AST into a set of
/// predicates that apply to the self type. A vector is returned
/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
--- /dev/null
+use super::ItemCtxt;
+use crate::astconv::{AstConv, SizedByDefault};
+use rustc_hir as hir;
+use rustc_infer::traits::util;
+use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::DefId;
+use rustc_span::Span;
+
+/// For associated types we include both bounds written on the type
+/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
+///
+/// Note that this filtering is done with the items identity substs to
+/// simplify checking that these bounds are met in impls. This means that
+/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
+/// `hr-associated-type-bound-1.rs`.
+fn associated_type_bounds<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ assoc_item_def_id: DefId,
+ bounds: &'tcx [hir::GenericBound<'tcx>],
+ span: Span,
+) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+ let item_ty = tcx.mk_projection(
+ assoc_item_def_id,
+ InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
+ );
+
+ let bounds = AstConv::compute_bounds(
+ &ItemCtxt::new(tcx, assoc_item_def_id),
+ item_ty,
+ bounds,
+ SizedByDefault::Yes,
+ span,
+ );
+
+ let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
+ let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
+
+ let bounds_from_parent =
+ trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.skip_binders() {
+ ty::PredicateAtom::Trait(tr, _) => tr.self_ty() == item_ty,
+ ty::PredicateAtom::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
+ ty::PredicateAtom::TypeOutlives(outlives) => outlives.0 == item_ty,
+ _ => false,
+ });
+
+ let all_bounds = tcx
+ .arena
+ .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent));
+ debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds);
+ all_bounds
+}
+
+/// Opaque types don't inherit bounds from their parent: for return position
+/// impl trait it isn't possible to write a suitable predicate on the
+/// containing function and for type-alias impl trait we don't have a backwards
+/// compatibility issue.
+fn opaque_type_bounds<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ opaque_def_id: DefId,
+ bounds: &'tcx [hir::GenericBound<'tcx>],
+ span: Span,
+) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+ let item_ty =
+ tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
+
+ let bounds = ty::print::with_no_queries(|| {
+ AstConv::compute_bounds(
+ &ItemCtxt::new(tcx, opaque_def_id),
+ item_ty,
+ bounds,
+ SizedByDefault::Yes,
+ span,
+ )
+ });
+
+ let bounds = bounds.predicates(tcx, item_ty);
+ debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);
+
+ tcx.arena.alloc_slice(&bounds)
+}
+
+pub(super) fn explicit_item_bounds(
+ tcx: TyCtxt<'_>,
+ def_id: DefId,
+) -> &'_ [(ty::Predicate<'_>, Span)] {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ match tcx.hir().get(hir_id) {
+ hir::Node::TraitItem(hir::TraitItem {
+ kind: hir::TraitItemKind::Type(bounds, _),
+ span,
+ ..
+ }) => associated_type_bounds(tcx, def_id, bounds, *span),
+ hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }),
+ span,
+ ..
+ }) => opaque_type_bounds(tcx, def_id, bounds, *span),
+ _ => bug!("item_bounds called on {:?}", def_id),
+ }
+}
+
+pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
+ tcx.mk_predicates(
+ util::elaborate_predicates(
+ tcx,
+ tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
+ )
+ .map(|obligation| obligation.predicate),
+ )
+}
infcx,
tcx.param_env(impl1_def_id),
tcx.hir().local_def_id_to_hir_id(impl1_def_id),
+ 0,
arg,
span,
) {
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::middle::stability;
use rustc_middle::ty::fold::TypeFolder;
-use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt};
use rustc_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn};
use rustc_span::hygiene::MacroKind;
ty::AssocKind::Type => {
let my_name = self.ident.name.clean(cx);
- if let ty::TraitContainer(did) = self.container {
- // When loading a cross-crate associated type, the bounds for this type
- // are actually located on the trait/impl itself, so we need to load
- // all of the generics from there and then look for bounds that are
- // applied to this associated type in question.
- let predicates = cx.tcx.explicit_predicates_of(did);
- let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
+ if let ty::TraitContainer(_) = self.container {
+ let bounds = cx.tcx.explicit_item_bounds(self.def_id);
+ let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
+ let generics = (cx.tcx.generics_of(self.def_id), predicates).clean(cx);
let mut bounds = generics
.where_predicates
.iter()
ty::Opaque(def_id, substs) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
- // by looking up the projections associated with the def_id.
- let predicates_of = cx.tcx.explicit_predicates_of(def_id);
+ // by looking up the bounds associated with the def_id.
let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
- let bounds = predicates_of.instantiate(cx.tcx, substs);
+ let bounds = cx
+ .tcx
+ .explicit_item_bounds(def_id)
+ .iter()
+ .map(|(bound, _)| bound.subst(cx.tcx, substs))
+ .collect::<Vec<_>>();
let mut regions = vec![];
let mut has_sized = false;
let mut bounds = bounds
- .predicates
.iter()
- .filter_map(|predicate| {
+ .filter_map(|bound| {
// Note: The substs of opaque types can contain unbound variables,
// meaning that we have to use `ignore_quantifiers_with_unbound_vars` here.
- let trait_ref = match predicate.bound_atom(cx.tcx).skip_binder() {
+ let trait_ref = match bound.bound_atom(cx.tcx).skip_binder() {
ty::PredicateAtom::Trait(tr, _constness) => {
ty::Binder::bind(tr.trait_ref)
}
}
let bounds: Vec<_> = bounds
- .predicates
.iter()
- .filter_map(|pred| {
+ .filter_map(|bound| {
if let ty::PredicateAtom::Projection(proj) =
- pred.bound_atom(cx.tcx).skip_binder()
+ bound.bound_atom(cx.tcx).skip_binder()
{
if proj.projection_ty.trait_ref(cx.tcx)
== trait_ref.skip_binder()
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
- inner: OpaqueTyItem(
- OpaqueTy {
- bounds: self.opaque_ty.bounds.clean(cx),
- generics: self.opaque_ty.generics.clean(cx),
- },
- false,
- ),
+ inner: OpaqueTyItem(OpaqueTy {
+ bounds: self.opaque_ty.bounds.clean(cx),
+ generics: self.opaque_ty.generics.clean(cx),
+ }),
}
}
}
FunctionItem(Function),
ModuleItem(Module),
TypedefItem(Typedef, bool /* is associated type */),
- OpaqueTyItem(OpaqueTy, bool /* is associated type */),
+ OpaqueTyItem(OpaqueTy),
StaticItem(Static),
ConstantItem(Constant),
TraitItem(Trait),
clean::ConstantItem(ref c) => item_constant(buf, cx, item, c),
clean::ForeignTypeItem => item_foreign_type(buf, cx, item, cache),
clean::KeywordItem(_) => item_keyword(buf, cx, item),
- clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e, cache),
+ clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e, cache),
clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta, cache),
_ => {
// We don't generate pages for any other type.
// revisions: rpass cfail
-trait Tr {
+trait Tr
+where
+ (Self::Arr,): Sized,
+{
type Arr;
const C: usize = 0;
bb5: {
StorageDead(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
- _0 = <Option<Box<u32>> as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
+ _0 = <Option<Box<u32>> as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20
// mir::Constant
// + span: $DIR/issue-62289.rs:9:15: 9:20
// + literal: Const { ty: fn(<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::Error) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error}, val: Value(Scalar(<ZST>)) }
scope 8 {
- debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+ debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15
+ let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
}
}
}
}
scope 8 {
debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15
+ let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
}
}
}
}
scope 8 {
debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15
+ let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
}
}
}
scope 8 {
- debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+ debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15
+ let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
}
}
}
}
scope 8 {
debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15
+ let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
}
}
}
--- /dev/null
+// Check that `where Self::Output: Copy` is turned into a bound on `Op::Output`.
+
+//check-pass
+
+trait Op
+where
+ Self::Output: Copy,
+{
+ type Output;
+}
+
+fn duplicate<T: Op>(x: T::Output) -> (T::Output, T::Output) {
+ (x, x)
+}
+
+fn main() {}
fn main() {}
-trait Bar { type Assoc; }
+trait Bar {
+ type Assoc;
+}
trait Thing {
type Out;
}
struct AssocNoCopy;
-impl Bar for AssocNoCopy { type Assoc = String; }
+impl Bar for AssocNoCopy {
+ type Assoc = String;
+}
impl Thing for AssocNoCopy {
type Out = Box<dyn Bar<Assoc: Copy>>;
//~^ ERROR the trait bound `String: Copy` is not satisfied
+ //~| ERROR the trait bound `String: Copy` is not satisfied
fn func() -> Self::Out {
Box::new(AssocNoCopy)
error[E0277]: the trait bound `String: Copy` is not satisfied
- --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:26:28
+ --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
|
LL | type Out = Box<dyn Bar<Assoc: Copy>>;
| ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+ --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
|
- = note: the return type of a function must have a statically known size
+LL | type Out = Box<dyn Bar<Assoc: Copy>>;
+ | ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
-error: aborting due to previous error
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
use std::fmt::Debug;
use std::iter::Once;
-trait Lam<Binder> { type App; }
+trait Lam<Binder> {
+ type App;
+}
#[derive(Clone)]
struct L1;
-impl<'a> Lam<&'a u8> for L1 { type App = u8; }
+impl<'a> Lam<&'a u8> for L1 {
+ type App = u8;
+}
#[derive(Clone)]
struct L2;
-impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; }
+impl<'a, 'b> Lam<&'a &'b u8> for L2 {
+ type App = u8;
+}
trait Case1 {
- type C: Clone + Iterator<Item:
- Send + Iterator<Item:
- for<'a> Lam<&'a u8, App:
- Debug
- >
- > + Sync>;
+ type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+ //~^ ERROR `<<Self as Case1>::C as Iterator>::Item` is not an iterator
+ //~| ERROR `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+ //~| ERROR `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
}
pub struct S1;
impl Case1 for S1 {
-//~^ ERROR `<L1 as Lam<&'a u8>>::App` doesn't implement `Debug` [E0277]
type C = Once<Once<L1>>;
}
fn assume_case1<T: Case1>() {
-//~^ ERROR `<_ as Lam<&'a u8>>::App` doesn't implement `Debug` [E0277]
-//~| ERROR `<<T as Case1>::C as Iterator>::Item` is not an iterator [E0277]
-//~| ERROR `<<T as Case1>::C as Iterator>::Item` cannot be sent between threads safely [E0277]
-//~| ERROR `<<T as Case1>::C as Iterator>::Item` cannot be shared between threads safely [E0277]
- fn assert_a<_0, A>() where A: Iterator<Item = _0>, _0: Debug {}
+ fn assert_a<_0, A>()
+ where
+ A: Iterator<Item = _0>,
+ _0: Debug,
+ {
+ }
assert_a::<_, T::A>();
- fn assert_b<_0, B>() where B: Iterator<Item = _0>, _0: 'static {}
+ fn assert_b<_0, B>()
+ where
+ B: Iterator<Item = _0>,
+ _0: 'static,
+ {
+ }
assert_b::<_, T::B>();
fn assert_c<_0, _1, _2, C>()
_2: Send + Iterator<Item = _1>,
_1: for<'a> Lam<&'a u8, App = _0>,
_0: Debug,
- {}
+ {
+ }
assert_c::<_, _, _, T::C>();
}
-error[E0277]: `<L1 as Lam<&'a u8>>::App` doesn't implement `Debug`
- --> $DIR/bad-bounds-on-assoc-in-trait.rs:29:6
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` is not an iterator
+ --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:5
|
-LL | trait Case1 {
- | ----- required by a bound in this
-...
-LL | Debug
- | ----- required by this bound in `Case1`
-...
-LL | impl Case1 for S1 {
- | ^^^^^ `<L1 as Lam<&'a u8>>::App` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<<Self as Case1>::C as Iterator>::Item` is not an iterator
|
- = help: the trait `for<'a> Debug` is not implemented for `<L1 as Lam<&'a u8>>::App`
-
-error[E0277]: `<<T as Case1>::C as Iterator>::Item` is not an iterator
- --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20
- |
-LL | fn assume_case1<T: Case1>() {
- | ^^^^^ `<<T as Case1>::C as Iterator>::Item` is not an iterator
- |
- = help: the trait `Iterator` is not implemented for `<<T as Case1>::C as Iterator>::Item`
+ = help: the trait `Iterator` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
help: consider further restricting the associated type
|
-LL | fn assume_case1<T: Case1>() where <<T as Case1>::C as Iterator>::Item: Iterator {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0277]: `<<T as Case1>::C as Iterator>::Item` cannot be sent between threads safely
- --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+ --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:36
+ |
+LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+ | ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+ |
+ ::: $SRC_DIR/core/src/marker.rs:LL:COL
|
-LL | trait Case1 {
- | ----- required by a bound in this
-LL | type C: Clone + Iterator<Item:
-LL | Send + Iterator<Item:
- | ---- required by this bound in `Case1`
-...
-LL | fn assume_case1<T: Case1>() {
- | ^^^^^ `<<T as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+LL | pub unsafe auto trait Send {
+ | -------------------------- required by this bound in `Send`
|
- = help: the trait `Send` is not implemented for `<<T as Case1>::C as Iterator>::Item`
+ = help: the trait `Send` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
help: consider further restricting the associated type
|
-LL | fn assume_case1<T: Case1>() where <<T as Case1>::C as Iterator>::Item: Send {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0277]: `<<T as Case1>::C as Iterator>::Item` cannot be shared between threads safely
- --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
+ --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:93
|
-LL | trait Case1 {
- | ----- required by a bound in this
-...
-LL | > + Sync>;
- | ---- required by this bound in `Case1`
-...
-LL | fn assume_case1<T: Case1>() {
- | ^^^^^ `<<T as Case1>::C as Iterator>::Item` cannot be shared between threads safely
+LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+ | ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
+ |
+ ::: $SRC_DIR/core/src/marker.rs:LL:COL
|
- = help: the trait `Sync` is not implemented for `<<T as Case1>::C as Iterator>::Item`
-help: consider further restricting the associated type
- |
-LL | fn assume_case1<T: Case1>() where <<T as Case1>::C as Iterator>::Item: Sync {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `Debug`
- --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20
+LL | pub unsafe auto trait Sync {
+ | -------------------------- required by this bound in `Sync`
|
-LL | trait Case1 {
- | ----- required by a bound in this
-...
-LL | Debug
- | ----- required by this bound in `Case1`
-...
-LL | fn assume_case1<T: Case1>() {
- | ^^^^^ `<_ as Lam<&'a u8>>::App` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ = help: the trait `Sync` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
+help: consider further restricting the associated type
|
- = help: the trait `for<'a> Debug` is not implemented for `<_ as Lam<&'a u8>>::App`
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.
-// check-pass
-
#![feature(associated_type_bounds)]
use std::fmt::Debug;
trait Case1 {
type A: Iterator<Item: Debug>;
+ //~^ ERROR `<<Self as Case1>::A as Iterator>::Item` doesn't implement `Debug`
type B: Iterator<Item: 'static>;
}
// Ensure we don't have opaque `impl Trait` desugaring:
+// What is this supposed to mean? Rustc currently lowers `: Default` in the
+// bounds of `Out`, but trait selection can't find the bound since it applies
+// to a type other than `Self::Out`.
pub trait Foo { type Out: Baz<Assoc: Default>; }
+//~^ ERROR trait bound `<<Self as Foo>::Out as Baz>::Assoc: Default` is not satisfied
pub trait Baz { type Assoc; }
#[derive(Default)]
--- /dev/null
+error[E0277]: `<<Self as Case1>::A as Iterator>::Item` doesn't implement `Debug`
+ --> $DIR/bounds-on-assoc-in-trait.rs:18:28
+ |
+LL | type A: Iterator<Item: Debug>;
+ | ^^^^^ `<<Self as Case1>::A as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+ |
+LL | pub trait Debug {
+ | --------------- required by this bound in `Debug`
+ |
+ = help: the trait `Debug` is not implemented for `<<Self as Case1>::A as Iterator>::Item`
+help: consider further restricting the associated type
+ |
+LL | trait Case1 where <<Self as Case1>::A as Iterator>::Item: Debug {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `<<Self as Foo>::Out as Baz>::Assoc: Default` is not satisfied
+ --> $DIR/bounds-on-assoc-in-trait.rs:35:38
+ |
+LL | pub trait Foo { type Out: Baz<Assoc: Default>; }
+ | ^^^^^^^ the trait `Default` is not implemented for `<<Self as Foo>::Out as Baz>::Assoc`
+ |
+ ::: $SRC_DIR/core/src/default.rs:LL:COL
+ |
+LL | pub trait Default: Sized {
+ | ------------------------ required by this bound in `Default`
+ |
+help: consider further restricting the associated type
+ |
+LL | pub trait Foo where <<Self as Foo>::Out as Baz>::Assoc: Default { type Out: Baz<Assoc: Default>; }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
| |
| `Item` bound here first
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
- --> $DIR/duplicate.rs:145:43
- |
-LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
- | ---------- ^^^^^^^^^^ re-bound here
- | |
- | `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
- --> $DIR/duplicate.rs:147:43
- |
-LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
- | ---------- ^^^^^^^^^^ re-bound here
- | |
- | `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
- --> $DIR/duplicate.rs:149:46
- |
-LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
- | ------------- ^^^^^^^^^^^^^ re-bound here
- | |
- | `Item` bound here first
-
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:152:40
|
| |
| `Item` bound here first
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:145:43
+ |
+LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:147:43
+ |
+LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:149:46
+ |
+LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
error: aborting due to 69 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0719`.
--- /dev/null
+// Make sure that we normalize bounds on associated types before checking them
+// as candidates.
+
+// check-pass
+
+trait Mul<T> {
+ type Output;
+}
+
+trait Matrix: Mul<<Self as Matrix>::Row, Output = ()> {
+ type Row;
+
+ type Transpose: Matrix<Row = Self::Row>;
+}
+
+fn is_mul<S, T: Mul<S, Output = ()>>() {}
+
+fn f<T: Matrix>() {
+ // The unnormalized bound on `T::Transpose` is
+ // `Mul<<T::Transpose as Matrix>::Row` which has to be normalized to be
+ // equal to `T::Row`.
+ is_mul::<T::Row, T::Transpose>();
+}
+
+fn main() {}
--- /dev/null
+// Make sure that if there are multiple applicable bounds on a projection, we
+// consider them ambiguous. In this test we are initially trying to solve
+// `Self::Repr: From<_>`, which is ambiguous until we later infer `_` to
+// `{integer}`.
+
+// check-pass
+
+trait PrimeField: Sized {
+ type Repr: From<u64> + From<Self>;
+ type Repr2: From<Self> + From<u64>;
+
+ fn method() {
+ Self::Repr::from(10);
+ Self::Repr2::from(10);
+ }
+}
+
+fn function<T: PrimeField>() {
+ T::Repr::from(10);
+ T::Repr2::from(10);
+}
+
+fn main() {}
--- /dev/null
+// Check that if we have multiple applicable projection bounds we pick one (for
+// backwards compatibility reasons).
+
+// check-pass
+use std::ops::Mul;
+
+trait A {
+ type V;
+ type U: Mul<Self::V, Output = ()> + Mul<(), Output = ()>;
+}
+
+fn g<T: A<V = ()>>() {
+ let y: <T::U as Mul<()>>::Output = ();
+}
+
+fn main() {}
-error[E0284]: type annotations needed
+error[E0283]: type annotations needed
--> $DIR/associated-types-unconstrained.rs:14:20
|
+LL | fn bar() -> isize;
+ | ------------------ required by `Foo::bar`
+...
LL | let x: isize = Foo::bar();
| ^^^^^^^^ cannot infer type
|
- = note: cannot satisfy `<_ as Foo>::A == _`
+ = note: cannot satisfy `_: Foo`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0283`.
type B = Self::A;
}
-// ...but is an error in any impl that doesn't override at least one of the defaults
impl Tr for () {}
-//~^ ERROR overflow evaluating the requirement
-// As soon as at least one is redefined, it works:
impl Tr for u8 {
type A = u8;
}
type B = u8;
}
-// ...but only if this actually breaks the cycle
+// ...but not in an impl that redefines one of the types.
impl Tr for bool {
- //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
type A = Box<Self::B>;
//~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
}
// (the error is shown twice for some reason)
impl Tr for usize {
- //~^ ERROR type mismatch resolving `<usize as Tr>::B == _`
type B = &'static Self::A;
//~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
}
-error[E0275]: overflow evaluating the requirement `<() as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-1.rs:10:6
- |
-LL | impl Tr for () {}
- | ^^
-
-error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-1.rs:28:6
- |
-LL | impl Tr for bool {
- | ^^ cyclic type of infinite size
-
-error[E0271]: type mismatch resolving `<usize as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-1.rs:35:6
- |
-LL | impl Tr for usize {
- | ^^ cyclic type of infinite size
-
error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-1.rs:30:5
+ --> $DIR/defaults-cyclic-fail-1.rs:26:5
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
- --> $DIR/defaults-cyclic-fail-1.rs:37:5
+ --> $DIR/defaults-cyclic-fail-1.rs:32:5
|
LL | type B = &'static Self::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0271, E0275.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0271`.
type B = Box<Self::A>;
}
-// ...but is an error in any impl that doesn't override at least one of the defaults
impl Tr for () {}
-//~^ ERROR type mismatch resolving `<() as Tr>::B == _`
-// As soon as at least one is redefined, it works:
impl Tr for u8 {
type A = u8;
}
type B = u8;
}
-// ...but only if this actually breaks the cycle
impl Tr for bool {
- //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
type A = Box<Self::B>;
//~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
}
// (the error is shown twice for some reason)
impl Tr for usize {
- //~^ ERROR type mismatch resolving `<usize as Tr>::B == _`
type B = &'static Self::A;
//~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
}
-error[E0271]: type mismatch resolving `<() as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-2.rs:12:6
- |
-LL | impl Tr for () {}
- | ^^ cyclic type of infinite size
-
-error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-2.rs:30:6
- |
-LL | impl Tr for bool {
- | ^^ cyclic type of infinite size
-
-error[E0271]: type mismatch resolving `<usize as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-2.rs:37:6
- |
-LL | impl Tr for usize {
- | ^^ cyclic type of infinite size
-
error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-2.rs:32:5
+ --> $DIR/defaults-cyclic-fail-2.rs:27:5
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
- --> $DIR/defaults-cyclic-fail-2.rs:39:5
+ --> $DIR/defaults-cyclic-fail-2.rs:33:5
|
LL | type B = &'static Self::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0271`.
//! Checks that associated type defaults are properly validated.
//!
//! This means:
-//! * Default types are wfchecked
//! * Default types are checked against where clauses on the assoc. type
-//! (eg. `type Assoc: Clone = NotClone`), and also against where clauses on
-//! the trait itself when possible
+//! (eg. `type Assoc: Clone = NotClone`)
#![feature(associated_type_defaults)]
}
// Where-clauses defined on the trait must also be considered
-trait Tr2 where Self::Ty: Clone {
- //~^ ERROR the trait bound `NotClone: Clone` is not satisfied
+trait Tr2
+where
+ Self::Ty: Clone,
+{
type Ty = NotClone;
-}
-
-// Independent of where-clauses (there are none here), default types must always be wf
-trait Tr3 {
- type Ty = Vec<[u8]>;
- //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+ //~^ ERROR the trait bound `NotClone: Clone` is not satisfied
}
// Involved type parameters must fulfill all bounds required by defaults that mention them
trait IsU8<T> {}
impl<T> IsU8<u8> for T {}
-// Test that mentioning the assoc. type inside where clauses works
+// Test that mentioning the assoc. type inside where clauses is not allowed
trait C where
Vec<Self::Assoc>: Clone,
Self::Assoc: IsU8<Self::Assoc>,
// Test that we get all expected errors if that default is unsuitable
trait D where
Vec<Self::Assoc>: Clone,
- //~^ ERROR the trait bound `NotClone: Clone` is not satisfied
Self::Assoc: IsU8<Self::Assoc>,
- //~^ ERROR the trait bound `NotClone: IsU8<NotClone>` is not satisfied
bool: IsU8<Self::Assoc>,
- //~^ ERROR the trait bound `bool: IsU8<NotClone>` is not satisfied
{
type Assoc = NotClone;
+ //~^ ERROR the trait bound `NotClone: IsU8<NotClone>` is not satisfied
}
// Test behavior of the check when defaults refer to other defaults:
// Adding the `Baz: Clone` bound isn't enough since the default is type
// parameter `T`, which also might not be `Clone`.
-trait Foo3<T> where
+trait Foo3<T>
+where
Self::Bar: Clone,
Self::Baz: Clone,
- //~^ ERROR the trait bound `T: Clone` is not satisfied
{
type Bar = Vec<Self::Baz>;
type Baz = T;
+ //~^ ERROR the trait bound `T: Clone` is not satisfied
}
// This one finally works, with `Clone` bounds on all assoc. types and the type
// parameter.
-trait Foo4<T> where
+trait Foo4<T>
+where
T: Clone,
{
type Bar: Clone = Vec<Self::Baz>;
error[E0277]: the trait bound `NotClone: Clone` is not satisfied
- --> $DIR/defaults-suitability.rs:15:14
+ --> $DIR/defaults-suitability.rs:13:5
|
-LL | trait Tr {
- | -------- required by `Tr`
LL | type Ty: Clone = NotClone;
- | ^^^^^ the trait `Clone` is not implemented for `NotClone`
+ | ^^^^^^^^^-----^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `Tr::Ty`
+ | the trait `Clone` is not implemented for `NotClone`
error[E0277]: the trait bound `NotClone: Clone` is not satisfied
- --> $DIR/defaults-suitability.rs:20:27
- |
-LL | trait Tr2 where Self::Ty: Clone {
- | --------------------------^^^^^
- | | |
- | | the trait `Clone` is not implemented for `NotClone`
- | required by `Tr2`
+ --> $DIR/defaults-suitability.rs:22:5
+ |
+LL | Self::Ty: Clone,
+ | ----- required by this bound in `Tr2::Ty`
+LL | {
+LL | type Ty = NotClone;
+ | ^^^^^--^^^^^^^^^^^^
+ | | |
+ | | required by a bound in this
+ | the trait `Clone` is not implemented for `NotClone`
error[E0277]: the trait bound `T: Clone` is not satisfied
- --> $DIR/defaults-suitability.rs:33:15
+ --> $DIR/defaults-suitability.rs:28:5
|
-LL | trait Foo<T> {
- | ------------ required by `Foo`
LL | type Bar: Clone = Vec<T>;
- | ^^^^^ the trait `Clone` is not implemented for `T`
+ | ^^^^^^^^^^-----^^^^^^^^^^
+ | | |
+ | | required by this bound in `Foo::Bar`
+ | the trait `Clone` is not implemented for `T`
|
= note: required because of the requirements on the impl of `Clone` for `Vec<T>`
help: consider restricting type parameter `T`
| ^^^^^^^
error[E0277]: the trait bound `(): Foo<Self>` is not satisfied
- --> $DIR/defaults-suitability.rs:39:17
+ --> $DIR/defaults-suitability.rs:34:5
|
-LL | trait Bar: Sized {
- | ---------------- required by `Bar`
-LL | // `(): Foo<Self>` might hold for some possible impls but not all.
LL | type Assoc: Foo<Self> = ();
- | ^^^^^^^^^ the trait `Foo<Self>` is not implemented for `()`
+ | ^^^^^^^^^^^^---------^^^^^^
+ | | |
+ | | required by this bound in `Bar::Assoc`
+ | the trait `Foo<Self>` is not implemented for `()`
error[E0277]: the trait bound `NotClone: IsU8<NotClone>` is not satisfied
- --> $DIR/defaults-suitability.rs:59:18
- |
-LL | / trait D where
-LL | | Vec<Self::Assoc>: Clone,
-LL | |
-LL | | Self::Assoc: IsU8<Self::Assoc>,
- | | ^^^^^^^^^^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `NotClone`
-... |
-LL | | type Assoc = NotClone;
-LL | | }
- | |_- required by `D`
-
-error[E0277]: the trait bound `bool: IsU8<NotClone>` is not satisfied
- --> $DIR/defaults-suitability.rs:61:11
- |
-LL | / trait D where
-LL | | Vec<Self::Assoc>: Clone,
-LL | |
-LL | | Self::Assoc: IsU8<Self::Assoc>,
-LL | |
-LL | | bool: IsU8<Self::Assoc>,
- | | ^^^^^^^^^^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `bool`
-... |
-LL | | type Assoc = NotClone;
-LL | | }
- | |_- required by `D`
-
-error[E0277]: the trait bound `NotClone: Clone` is not satisfied
- --> $DIR/defaults-suitability.rs:57:23
- |
-LL | / trait D where
-LL | | Vec<Self::Assoc>: Clone,
- | | ^^^^^ the trait `Clone` is not implemented for `NotClone`
-LL | |
-LL | | Self::Assoc: IsU8<Self::Assoc>,
-... |
-LL | | type Assoc = NotClone;
-LL | | }
- | |_- required by `D`
- |
- = note: required because of the requirements on the impl of `Clone` for `Vec<NotClone>`
+ --> $DIR/defaults-suitability.rs:56:5
+ |
+LL | Self::Assoc: IsU8<Self::Assoc>,
+ | ----------------- required by this bound in `D::Assoc`
+...
+LL | type Assoc = NotClone;
+ | ^^^^^-----^^^^^^^^^^^^
+ | | |
+ | | required by a bound in this
+ | the trait `IsU8<NotClone>` is not implemented for `NotClone`
error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied
- --> $DIR/defaults-suitability.rs:72:15
+ --> $DIR/defaults-suitability.rs:65:5
|
-LL | trait Foo2<T> {
- | ------------- required by `Foo2`
LL | type Bar: Clone = Vec<Self::Baz>;
- | ^^^^^ the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`
+ | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `Foo2::Bar`
+ | the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`
|
= note: required because of the requirements on the impl of `Clone` for `Vec<<Self as Foo2<T>>::Baz>`
help: consider further restricting the associated type
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: Clone` is not satisfied
- --> $DIR/defaults-suitability.rs:81:15
+ --> $DIR/defaults-suitability.rs:74:5
|
-LL | trait Foo25<T: Clone> {
- | --------------------- required by `Foo25`
LL | type Bar: Clone = Vec<Self::Baz>;
- | ^^^^^ the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`
+ | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `Foo25::Bar`
+ | the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`
|
= note: required because of the requirements on the impl of `Clone` for `Vec<<Self as Foo25<T>>::Baz>`
help: consider further restricting the associated type
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `T: Clone` is not satisfied
- --> $DIR/defaults-suitability.rs:90:16
- |
-LL | / trait Foo3<T> where
-LL | | Self::Bar: Clone,
-LL | | Self::Baz: Clone,
- | | ^^^^^ the trait `Clone` is not implemented for `T`
-LL | |
-... |
-LL | | type Baz = T;
-LL | | }
- | |_- required by `Foo3`
+ --> $DIR/defaults-suitability.rs:87:5
+ |
+LL | Self::Baz: Clone,
+ | ----- required by this bound in `Foo3::Baz`
+...
+LL | type Baz = T;
+ | ^^^^^---^^^^^
+ | | |
+ | | required by a bound in this
+ | the trait `Clone` is not implemented for `T`
|
help: consider further restricting type parameter `T`
|
LL | Self::Baz: Clone, T: Clone
| ^^^^^^^^^^
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
- --> $DIR/defaults-suitability.rs:27:5
- |
-LL | type Ty = Vec<[u8]>;
- | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
- |
- ::: $SRC_DIR/alloc/src/vec.rs:LL:COL
- |
-LL | pub struct Vec<T> {
- | - required by this bound in `Vec`
- |
- = help: the trait `Sized` is not implemented for `[u8]`
-
-error: aborting due to 11 previous errors
+error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0277`.
use std::{
fmt::Display,
- ops::{AddAssign, Deref}
+ ops::{AddAssign, Deref},
};
-
trait UncheckedCopy: Sized {
// This Output is said to be Copy. Yet we default to Self
// and it's accepted, not knowing if Self ineed is Copy
- type Output: Copy
+ type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
//~^ ERROR the trait bound `Self: Copy` is not satisfied
- + Deref<Target = str>
- //~^ ERROR the trait bound `Self: Deref` is not satisfied
- + AddAssign<&'static str>
- //~^ ERROR cannot add-assign `&'static str` to `Self`
- + From<Self>
- + Display = Self;
- //~^ ERROR `Self` doesn't implement `std::fmt::Display`
+ //~| ERROR the trait bound `Self: Deref` is not satisfied
+ //~| ERROR cannot add-assign `&'static str` to `Self`
+ //~| ERROR `Self` doesn't implement `std::fmt::Display`
// We said the Output type was Copy, so we can Copy it freely!
fn unchecked_copy(other: &Self::Output) -> Self::Output {
}
impl<T> UncheckedCopy for T {}
-//~^ ERROR `T` doesn't implement `std::fmt::Display`
-//~| ERROR the trait bound `T: Deref` is not satisfied
-//~| ERROR cannot add-assign `&'static str` to `T`
-//~| ERROR the trait bound `T: Copy` is not satisfied
fn bug<T: UncheckedCopy>(origin: T) {
let origin = T::make_origin(origin);
-error[E0277]: the trait bound `Self: Copy` is not satisfied
- --> $DIR/defaults-unsound-62211-1.rs:21:18
- |
-LL | trait UncheckedCopy: Sized {
- | -------------------------- required by `UncheckedCopy`
-...
-LL | type Output: Copy
- | ^^^^ the trait `Copy` is not implemented for `Self`
- |
-help: consider further restricting `Self`
- |
-LL | trait UncheckedCopy: Sized + Copy {
- | ^^^^^^
-
-error[E0277]: cannot add-assign `&'static str` to `Self`
- --> $DIR/defaults-unsound-62211-1.rs:25:7
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+ --> $DIR/defaults-unsound-62211-1.rs:20:5
|
-LL | trait UncheckedCopy: Sized {
- | -------------------------- required by `UncheckedCopy`
-...
-LL | + AddAssign<&'static str>
- | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^
+ | | |
+ | | required by this bound in `UncheckedCopy::Output`
+ | `Self` cannot be formatted with the default formatter
|
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
help: consider further restricting `Self`
|
-LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait UncheckedCopy: Sized + std::fmt::Display {
+ | ^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `Self: Deref` is not satisfied
- --> $DIR/defaults-unsound-62211-1.rs:23:7
+ --> $DIR/defaults-unsound-62211-1.rs:20:5
|
-LL | trait UncheckedCopy: Sized {
- | -------------------------- required by `UncheckedCopy`
-...
-LL | + Deref<Target = str>
- | ^^^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `Self`
+LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+ | ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `UncheckedCopy::Output`
+ | the trait `Deref` is not implemented for `Self`
|
help: consider further restricting `Self`
|
LL | trait UncheckedCopy: Sized + Deref {
| ^^^^^^^
-error[E0277]: `Self` doesn't implement `std::fmt::Display`
- --> $DIR/defaults-unsound-62211-1.rs:28:7
+error[E0277]: cannot add-assign `&'static str` to `Self`
+ --> $DIR/defaults-unsound-62211-1.rs:20:5
|
-LL | trait UncheckedCopy: Sized {
- | -------------------------- required by `UncheckedCopy`
-...
-LL | + Display = Self;
- | ^^^^^^^ `Self` cannot be formatted with the default formatter
+LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `UncheckedCopy::Output`
+ | no implementation for `Self += &'static str`
|
- = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
help: consider further restricting `Self`
|
-LL | trait UncheckedCopy: Sized + std::fmt::Display {
- | ^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `T` doesn't implement `std::fmt::Display`
- --> $DIR/defaults-unsound-62211-1.rs:41:9
- |
-LL | trait UncheckedCopy: Sized {
- | ------------- required by a bound in this
-...
-LL | + Display = Self;
- | ------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
- |
- = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-help: consider restricting type parameter `T`
- |
-LL | impl<T: std::fmt::Display> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `T: Deref` is not satisfied
- --> $DIR/defaults-unsound-62211-1.rs:41:9
- |
-LL | trait UncheckedCopy: Sized {
- | ------------- required by a bound in this
-...
-LL | + Deref<Target = str>
- | ------------------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^ the trait `Deref` is not implemented for `T`
- |
-help: consider restricting type parameter `T`
- |
-LL | impl<T: Deref> UncheckedCopy for T {}
- | ^^^^^^^
-
-error[E0277]: cannot add-assign `&'static str` to `T`
- --> $DIR/defaults-unsound-62211-1.rs:41:9
- |
-LL | trait UncheckedCopy: Sized {
- | ------------- required by a bound in this
-...
-LL | + AddAssign<&'static str>
- | ----------------------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^ no implementation for `T += &'static str`
- |
-help: consider restricting type parameter `T`
- |
-LL | impl<T: AddAssign<&'static str>> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0277]: the trait bound `T: Copy` is not satisfied
- --> $DIR/defaults-unsound-62211-1.rs:41:9
+error[E0277]: the trait bound `Self: Copy` is not satisfied
+ --> $DIR/defaults-unsound-62211-1.rs:20:5
|
-LL | trait UncheckedCopy: Sized {
- | ------------- required by a bound in this
-...
-LL | type Output: Copy
- | ---- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+ | ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `UncheckedCopy::Output`
+ | the trait `Copy` is not implemented for `Self`
|
-help: consider restricting type parameter `T`
+help: consider further restricting `Self`
|
-LL | impl<T: Copy> UncheckedCopy for T {}
- | ^^^^^^
+LL | trait UncheckedCopy: Sized + Copy {
+ | ^^^^^^
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.
use std::{
fmt::Display,
- ops::{AddAssign, Deref}
+ ops::{AddAssign, Deref},
};
-
trait UncheckedCopy: Sized {
// This Output is said to be Copy. Yet we default to Self
// and it's accepted, not knowing if Self ineed is Copy
- type Output: Copy
+ type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
//~^ ERROR the trait bound `Self: Copy` is not satisfied
- + Deref<Target = str>
- //~^ ERROR the trait bound `Self: Deref` is not satisfied
- + AddAssign<&'static str>
- //~^ ERROR cannot add-assign `&'static str` to `Self`
- + From<Self>
- + Display = Self;
- //~^ ERROR `Self` doesn't implement `std::fmt::Display`
+ //~| ERROR the trait bound `Self: Deref` is not satisfied
+ //~| ERROR cannot add-assign `&'static str` to `Self`
+ //~| ERROR `Self` doesn't implement `std::fmt::Display`
// We said the Output type was Copy, so we can Copy it freely!
fn unchecked_copy(other: &Self::Output) -> Self::Output {
}
impl<T> UncheckedCopy for T {}
-//~^ ERROR `T` doesn't implement `std::fmt::Display`
-//~| ERROR the trait bound `T: Deref` is not satisfied
-//~| ERROR cannot add-assign `&'static str` to `T`
-//~| ERROR the trait bound `T: Copy` is not satisfied
fn bug<T: UncheckedCopy>(origin: T) {
let origin = T::make_origin(origin);
-error[E0277]: the trait bound `Self: Copy` is not satisfied
- --> $DIR/defaults-unsound-62211-2.rs:21:18
- |
-LL | trait UncheckedCopy: Sized {
- | -------------------------- required by `UncheckedCopy`
-...
-LL | type Output: Copy
- | ^^^^ the trait `Copy` is not implemented for `Self`
- |
-help: consider further restricting `Self`
- |
-LL | trait UncheckedCopy: Sized + Copy {
- | ^^^^^^
-
-error[E0277]: cannot add-assign `&'static str` to `Self`
- --> $DIR/defaults-unsound-62211-2.rs:25:7
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+ --> $DIR/defaults-unsound-62211-2.rs:20:5
|
-LL | trait UncheckedCopy: Sized {
- | -------------------------- required by `UncheckedCopy`
-...
-LL | + AddAssign<&'static str>
- | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^
+ | | |
+ | | required by this bound in `UncheckedCopy::Output`
+ | `Self` cannot be formatted with the default formatter
|
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
help: consider further restricting `Self`
|
-LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait UncheckedCopy: Sized + std::fmt::Display {
+ | ^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `Self: Deref` is not satisfied
- --> $DIR/defaults-unsound-62211-2.rs:23:7
+ --> $DIR/defaults-unsound-62211-2.rs:20:5
|
-LL | trait UncheckedCopy: Sized {
- | -------------------------- required by `UncheckedCopy`
-...
-LL | + Deref<Target = str>
- | ^^^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `Self`
+LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+ | ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `UncheckedCopy::Output`
+ | the trait `Deref` is not implemented for `Self`
|
help: consider further restricting `Self`
|
LL | trait UncheckedCopy: Sized + Deref {
| ^^^^^^^
-error[E0277]: `Self` doesn't implement `std::fmt::Display`
- --> $DIR/defaults-unsound-62211-2.rs:28:7
+error[E0277]: cannot add-assign `&'static str` to `Self`
+ --> $DIR/defaults-unsound-62211-2.rs:20:5
|
-LL | trait UncheckedCopy: Sized {
- | -------------------------- required by `UncheckedCopy`
-...
-LL | + Display = Self;
- | ^^^^^^^ `Self` cannot be formatted with the default formatter
+LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `UncheckedCopy::Output`
+ | no implementation for `Self += &'static str`
|
- = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
help: consider further restricting `Self`
|
-LL | trait UncheckedCopy: Sized + std::fmt::Display {
- | ^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `T` doesn't implement `std::fmt::Display`
- --> $DIR/defaults-unsound-62211-2.rs:41:9
- |
-LL | trait UncheckedCopy: Sized {
- | ------------- required by a bound in this
-...
-LL | + Display = Self;
- | ------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
- |
- = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-help: consider restricting type parameter `T`
- |
-LL | impl<T: std::fmt::Display> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `T: Deref` is not satisfied
- --> $DIR/defaults-unsound-62211-2.rs:41:9
- |
-LL | trait UncheckedCopy: Sized {
- | ------------- required by a bound in this
-...
-LL | + Deref<Target = str>
- | ------------------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^ the trait `Deref` is not implemented for `T`
- |
-help: consider restricting type parameter `T`
- |
-LL | impl<T: Deref> UncheckedCopy for T {}
- | ^^^^^^^
-
-error[E0277]: cannot add-assign `&'static str` to `T`
- --> $DIR/defaults-unsound-62211-2.rs:41:9
- |
-LL | trait UncheckedCopy: Sized {
- | ------------- required by a bound in this
-...
-LL | + AddAssign<&'static str>
- | ----------------------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^ no implementation for `T += &'static str`
- |
-help: consider restricting type parameter `T`
- |
-LL | impl<T: AddAssign<&'static str>> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0277]: the trait bound `T: Copy` is not satisfied
- --> $DIR/defaults-unsound-62211-2.rs:41:9
+error[E0277]: the trait bound `Self: Copy` is not satisfied
+ --> $DIR/defaults-unsound-62211-2.rs:20:5
|
-LL | trait UncheckedCopy: Sized {
- | ------------- required by a bound in this
-...
-LL | type Output: Copy
- | ---- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
- | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+ | ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `UncheckedCopy::Output`
+ | the trait `Copy` is not implemented for `Self`
|
-help: consider restricting type parameter `T`
+help: consider further restricting `Self`
|
-LL | impl<T: Copy> UncheckedCopy for T {}
- | ^^^^^^
+LL | trait UncheckedCopy: Sized + Copy {
+ | ^^^^^^
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Check that associated type defaults are wf checked.
+
+#![feature(associated_type_defaults)]
+
+// Default types must always be wf
+trait Tr3 {
+ type Ty = Vec<[u8]>;
+ //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+}
+
+fn main() {}
--- /dev/null
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/defaults-wf.rs:7:5
+ |
+LL | type Ty = Vec<[u8]>;
+ | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ ::: $SRC_DIR/alloc/src/vec.rs:LL:COL
+ |
+LL | pub struct Vec<T> {
+ | - required by this bound in `Vec`
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
|
= note: expected associated type `<impl Bar as Foo>::Item`
found type `i32`
- = note: the return type of a function must have a statically known size
help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32`
|
LL | fn bar() -> impl Bar<Item = i32> {
// type-checked.
trait Foo<T: Default + ToString> {
- type Out: Default + ToString + ?Sized = dyn ToString; //~ error: not satisfied
+ type Out: Default + ToString + ?Sized = dyn ToString; //~ ERROR not satisfied
}
-impl Foo<u32> for () {} //~ error: not satisfied
-impl Foo<u64> for () {} //~ error: not satisfied
+impl Foo<u32> for () {}
+impl Foo<u64> for () {}
fn main() {
assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
+ //~^ ERROR no function or associated item named `default` found for trait object
}
error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied
- --> $DIR/issue-43924.rs:7:15
+ --> $DIR/issue-43924.rs:7:5
|
-LL | trait Foo<T: Default + ToString> {
- | -------------------------------- required by `Foo`
LL | type Out: Default + ToString + ?Sized = dyn ToString;
- | ^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)`
+ | ^^^^^^^^^^-------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | required by this bound in `Foo::Out`
+ | the trait `Default` is not implemented for `(dyn ToString + 'static)`
-error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied
- --> $DIR/issue-43924.rs:10:6
- |
-LL | trait Foo<T: Default + ToString> {
- | --- required by a bound in this
-LL | type Out: Default + ToString + ?Sized = dyn ToString;
- | ------- required by this bound in `Foo`
-...
-LL | impl Foo<u32> for () {}
- | ^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)`
-
-error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied
- --> $DIR/issue-43924.rs:11:6
+error[E0599]: no function or associated item named `default` found for trait object `(dyn ToString + 'static)` in the current scope
+ --> $DIR/issue-43924.rs:14:39
|
-LL | trait Foo<T: Default + ToString> {
- | --- required by a bound in this
-LL | type Out: Default + ToString + ?Sized = dyn ToString;
- | ------- required by this bound in `Foo`
-...
-LL | impl Foo<u64> for () {}
- | ^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)`
+LL | assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
+ | ^^^^^^^ function or associated item not found in `(dyn ToString + 'static)`
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/issue-63593.rs:9:5
|
-LL | trait MyTrait {
- | ------------- required by `MyTrait`
LL | type This = Self;
- | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ | ^^^^^^^^^^^^^^^^^
+ | |
+ | doesn't have a size known at compile-time
+ | required by this bound in `MyTrait::This`
|
help: consider further restricting `Self`
|
struct S;
impl MPU for S { }
-//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
trait MyWrite {
fn my_write(&self, _: &dyn MyDisplay) { }
// FulfillmentError(Obligation(predicate=Binder(TraitPredicate(<T as MyDisplay>)),
// depth=1),Unimplemented)
let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
+ //~^ ERROR the trait bound `T: MyDisplay` is not satisfied
closure(valref);
}
}
error[E0277]: the trait bound `T: MyDisplay` is not satisfied
- --> $DIR/issue-65774-1.rs:10:21
+ --> $DIR/issue-65774-1.rs:10:5
|
-LL | trait MPU {
- | --------- required by `MPU`
LL | type MpuConfig: MyDisplay = T;
- | ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T`
+ | ^^^^^^^^^^^^^^^^---------^^^^^
+ | | |
+ | | required by this bound in `MPU::MpuConfig`
+ | the trait `MyDisplay` is not implemented for `T`
error[E0277]: the trait bound `T: MyDisplay` is not satisfied
- --> $DIR/issue-65774-1.rs:16:6
+ --> $DIR/issue-65774-1.rs:44:76
|
-LL | trait MPU {
- | --- required by a bound in this
-LL | type MpuConfig: MyDisplay = T;
- | --------- required by this bound in `MPU`
-...
-LL | impl MPU for S { }
- | ^^^ the trait `MyDisplay` is not implemented for `T`
+LL | let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
+ | ^^^^^^^ the trait `MyDisplay` is not implemented for `T`
+ |
+ = note: required because of the requirements on the impl of `MyDisplay` for `&mut T`
+ = note: required for the cast to the object type `dyn MyDisplay`
error: aborting due to 2 previous errors
struct S;
impl MPU for S { }
-//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
trait MyWrite {
fn my_write(&self, _: &dyn MyDisplay) { }
// // `Unimplemented` selecting `Binder(<T as MyDisplay>)` during codegen
//
writer.my_write(valref)
+ //~^ ERROR the trait bound `T: MyDisplay` is not satisfied
// This one causes the ICE:
// FulfillmentError(Obligation(predicate=Binder(TraitPredicate(<T as MyDisplay>)),
error[E0277]: the trait bound `T: MyDisplay` is not satisfied
- --> $DIR/issue-65774-2.rs:10:21
+ --> $DIR/issue-65774-2.rs:10:5
|
-LL | trait MPU {
- | --------- required by `MPU`
LL | type MpuConfig: MyDisplay = T;
- | ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T`
+ | ^^^^^^^^^^^^^^^^---------^^^^^
+ | | |
+ | | required by this bound in `MPU::MpuConfig`
+ | the trait `MyDisplay` is not implemented for `T`
error[E0277]: the trait bound `T: MyDisplay` is not satisfied
- --> $DIR/issue-65774-2.rs:16:6
+ --> $DIR/issue-65774-2.rs:39:25
|
-LL | trait MPU {
- | --- required by a bound in this
-LL | type MpuConfig: MyDisplay = T;
- | --------- required by this bound in `MPU`
-...
-LL | impl MPU for S { }
- | ^^^ the trait `MyDisplay` is not implemented for `T`
+LL | writer.my_write(valref)
+ | ^^^^^^ the trait `MyDisplay` is not implemented for `T`
+ |
+ = note: required for the cast to the object type `dyn MyDisplay`
error: aborting due to 2 previous errors
struct Foo;
struct Foo2;
-impl Bar for Foo { //~ ERROR type mismatch resolving `<Foo2 as Bar2>::Ok == char`
+impl Bar for Foo {
type Ok = ();
type Sibling = Foo2;
+ //~^ ERROR type mismatch resolving `<Foo2 as Bar2>::Ok == char`
}
impl Bar2 for Foo2 {
type Ok = u32;
error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == char`
- --> $DIR/issue-72806.rs:12:6
+ --> $DIR/issue-72806.rs:14:5
|
-LL | impl Bar for Foo {
- | ^^^ expected `u32`, found `char`
+LL | type Sibling: Bar2<Ok=char>;
+ | ------- required by this bound in `Bar::Sibling`
+...
+LL | type Sibling = Foo2;
+ | ^^^^^^^^^^^^^^^^^^^^ expected `char`, found `u32`
error: aborting due to previous error
--- /dev/null
+// ignore-tidy-linelength
+
+// Check that we normalize super predicates for object candidates.
+
+// check-pass
+
+use std::ops::Index;
+
+fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
+ // To prove
+ // `dyn SVec<Item = T, Output = T>: SVec`
+ // we need to show
+ // `dyn SVec<Item = T, Output = T> as Index>::Output == <dyn SVec<Item = T, Output = T> as SVec>::Item`
+ // which, with the current normalization strategy, has to be eagerly
+ // normalized to:
+ // `dyn SVec<Item = T, Output = T> as Index>::Output == T`.
+ let _ = s.len();
+}
+
+trait SVec: Index<usize, Output = <Self as SVec>::Item> {
+ type Item;
+
+ fn len(&self) -> usize;
+}
+
+fn main() {}
--- /dev/null
+// Minimized case from typenum that didn't compile because:
+// - We tried to normalize the ParamEnv of the second impl
+// - This requires trying to normalize `GrEq<Self, Square<Square<U>>>`
+// - This requires proving `Square<Square<U>>: Sized` so that the first impl
+// applies
+// - This requires Providing `Square<Square<U>>` is well-formed, so that we
+// can use the `Sized` bound on `Mul::Output`
+// - This requires proving `Square<U>: Mul`
+// - But first we tried normalizing the whole obligation, including the
+// ParamEnv, which leads to a cycle error.
+
+// check-pass
+
+trait PrivateSquareRoot {}
+
+pub trait Mul<Rhs = Self> {
+ type Output;
+}
+
+pub trait IsGreaterOrEqual<Rhs> {
+ type Output;
+}
+
+pub type Square<A> = <A as Mul>::Output;
+pub type GrEq<A, B> = <A as IsGreaterOrEqual<B>>::Output;
+
+impl<A, B> IsGreaterOrEqual<B> for A {
+ type Output = ();
+}
+
+impl<U> PrivateSquareRoot for U
+where
+ U: Mul,
+ Square<U>: Mul,
+ GrEq<Self, Square<Square<U>>>: Sized,
+{
+}
+
+fn main() {}
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
}
-trait Baz where Self::Assoc: Bar {
+trait Baz
+where
+ Self::Assoc: Bar,
+{
type Assoc;
}
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
}
-trait Bat where <Self as Bat>::Assoc: Bar {
+trait Bat
+where
+ <Self as Bat>::Assoc: Bar,
+{
type Assoc;
}
error[E0277]: the trait bound `bool: Bar` is not satisfied
- --> $DIR/point-at-type-on-obligation-failure-2.rs:8:18
+ --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
|
-LL | trait Foo {
- | --- required by a bound in this
LL | type Assoc: Bar;
- | --- required by this bound in `Foo`
+ | --- required by this bound in `Foo::Assoc`
...
LL | type Assoc = bool;
- | ^^^^ the trait `Bar` is not implemented for `bool`
+ | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
error[E0277]: the trait bound `bool: Bar` is not satisfied
- --> $DIR/point-at-type-on-obligation-failure-2.rs:16:18
+ --> $DIR/point-at-type-on-obligation-failure-2.rs:19:5
|
-LL | trait Baz where Self::Assoc: Bar {
- | --- required by this bound in `Baz`
+LL | Self::Assoc: Bar,
+ | --- required by this bound in `Baz::Assoc`
+LL | {
+LL | type Assoc;
+ | ----- required by a bound in this
...
LL | type Assoc = bool;
- | ^^^^ the trait `Bar` is not implemented for `bool`
+ | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
error[E0277]: the trait bound `bool: Bar` is not satisfied
- --> $DIR/point-at-type-on-obligation-failure-2.rs:24:18
+ --> $DIR/point-at-type-on-obligation-failure-2.rs:30:5
|
-LL | trait Bat where <Self as Bat>::Assoc: Bar {
- | --- required by this bound in `Bat`
+LL | <Self as Bat>::Assoc: Bar,
+ | --- required by this bound in `Bat::Assoc`
+LL | {
+LL | type Assoc;
+ | ----- required by a bound in this
...
LL | type Assoc = bool;
- | ^^^^ the trait `Bar` is not implemented for `bool`
+ | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
error: aborting due to 3 previous errors
struct Foo2;
impl Bar for Foo {
- type Ok = (); //~ ERROR type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
+ type Ok = ();
type Sibling = Foo2;
+ //~^ ERROR type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
}
impl Bar2 for Foo2 {
type Ok = u32;
error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
- --> $DIR/point-at-type-on-obligation-failure.rs:13:15
+ --> $DIR/point-at-type-on-obligation-failure.rs:14:5
|
-LL | type Ok = ();
- | ^^ expected `u32`, found `()`
+LL | type Sibling: Bar2<Ok=Self::Ok>;
+ | ----------- required by this bound in `Bar::Sibling`
+...
+LL | type Sibling = Foo2;
+ | ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `u32`
error: aborting due to previous error
--- /dev/null
+// check-pass
+
+trait IntoIt {
+ type Item;
+}
+
+impl<I> IntoIt for I {
+ type Item = ();
+}
+
+trait BaseGraph
+where
+ <Self::VertexIter as IntoIt>::Item: Sized,
+{
+ type VertexIter: IntoIt;
+}
+
+fn main() {}
--- /dev/null
+// check-pass
+
+trait A {
+ type U: Copy;
+}
+
+trait B where
+ <Self::V as A>::U: Copy,
+{
+ type V: A;
+}
+
+fn main() {}
|
LL | fn get_future() -> impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
-LL |
-LL | panic!()
- | -------- this returned value is of type `!`
|
= help: the trait `Future` is not implemented for `()`
- = note: the return type of a function must have a statically known size
error[E0698]: type inside `async fn` body must be known in this context
--> $DIR/async-error-span.rs:13:9
|
LL | let _: i32 = tuple().0;
| ^
- |
-help: consider awaiting before field access
- |
-LL | let _: i32 = tuple().await.0;
- | ^^^^^^
error[E0609]: no field `a` on type `impl Future`
--> $DIR/issue-61076.rs:60:28
|
LL | let _: i32 = struct_().a;
| ^
- |
-help: consider awaiting before field access
- |
-LL | let _: i32 = struct_().await.a;
- | ^^^^^^
error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope
--> $DIR/issue-61076.rs:62:15
|
LL | struct_().method();
| ^^^^^^ method not found in `impl Future`
- |
-help: consider awaiting before this method call
- |
-LL | struct_().await.method();
- | ^^^^^^
error[E0308]: mismatched types
--> $DIR/issue-61076.rs:69:9
|
= note: expected opaque type `impl Future`
found struct `Tuple`
-help: consider awaiting on the future
- |
-LL | match tuple().await {
- | ^^^^^^
error: aborting due to 6 previous errors
error: future cannot be sent between threads safely
--> $DIR/issue-64130-4-async-move.rs:15:17
|
-LL | pub fn foo() -> impl Future + Send {
- | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
-...
-LL | / async move {
-LL | | match client.status() {
-LL | | 200 => {
-LL | | let _x = get().await;
-... |
-LL | | }
-LL | | }
- | |_____- this returned value is of type `impl Future`
+LL | pub fn foo() -> impl Future + Send {
+ | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)`
note: future is not `Send` as this value is used across an await
|
LL | match client.status() {
| ^^^^^^^^^^^^^^^
- = note: the return type of a function must have a statically known size
error: aborting due to previous error
error[E0515]: cannot return value referencing local variable `s`
- --> $DIR/issue-67765-async-diagnostic.rs:13:11
+ --> $DIR/issue-67765-async-diagnostic.rs:13:5
|
LL | let b = &s[..];
| - `s` is borrowed here
LL |
LL | Err(b)?;
- | ^ returns a value referencing data owned by the current function
+ | ^^^^^^^ returns a value referencing data owned by the current function
error: aborting due to previous error
|
LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
-LL |
-LL | async { (ty, ty1) }
- | ------------------- this returned value is of type `impl Future`
|
note: captured value is not `Send`
--> $DIR/issue-70818.rs:6:18
|
LL | async { (ty, ty1) }
| ^^^ has type `U` which is not `Send`
- = note: the return type of a function must have a statically known size
help: consider restricting type parameter `U`
|
LL | fn foo<T: Send, U: Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
// Implicit `T: Sized` bound.
impl<T> Foo for Option<T> { }
-impl Bar for () {
- type Item = i32;
-}
-
-impl<T> Bar for Option<T> {
- type Item = Option<T>;
-}
-
-impl Bar for f32 {
- type Item = f32;
- //~^ ERROR the trait bound `f32: Foo` is not satisfied
-}
-
trait Baz<U: ?Sized> where U: Foo { }
impl Baz<i32> for i32 { }
= help: the trait `Sized` is not implemented for `str`
error[E0277]: the trait bound `f32: Foo` is not satisfied
- --> $DIR/impl_wf.rs:27:17
- |
-LL | trait Bar {
- | --- required by a bound in this
-LL | type Item: Foo;
- | --- required by this bound in `Bar`
-...
-LL | type Item = f32;
- | ^^^ the trait `Foo` is not implemented for `f32`
-
-error[E0277]: the trait bound `f32: Foo` is not satisfied
- --> $DIR/impl_wf.rs:35:6
+ --> $DIR/impl_wf.rs:22:6
|
LL | trait Baz<U: ?Sized> where U: Foo { }
| --- required by this bound in `Baz`
LL | impl Baz<f32> for f32 { }
| ^^^^^^^^ the trait `Foo` is not implemented for `f32`
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Split out of impl_wf.rs to work around rust aborting compilation early
+
+// compile-flags: -Z chalk
+
+trait Foo: Sized { }
+
+trait Bar {
+ type Item: Foo;
+}
+
+impl Foo for i32 { }
+
+// Implicit `T: Sized` bound.
+impl<T> Foo for Option<T> { }
+
+impl Bar for () {
+ type Item = i32;
+}
+
+impl<T> Bar for Option<T> {
+ type Item = Option<T>;
+}
+
+impl Bar for f32 {
+ type Item = f32;
+ //~^ ERROR the trait bound `f32: Foo` is not satisfied
+}
+
+trait Baz<U: ?Sized> where U: Foo { }
+
+impl Baz<i32> for i32 { }
+
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `f32: Foo` is not satisfied
+ --> $DIR/impl_wf_2.rs:25:5
+ |
+LL | type Item: Foo;
+ | --- required by this bound in `Bar::Item`
+...
+LL | type Item = f32;
+ | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `f32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
fn main() {
(&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
//~^ ERROR: type mismatch in closure arguments
+ //~| ERROR: size for values of type `<u32 as T<'_>>::V` cannot be known at compilation time
}
|
= note: required for the cast to the object type `dyn for<'x> Fn(<u32 as T<'x>>::V)`
-error: aborting due to previous error
+error[E0277]: the size for values of type `<u32 as T<'_>>::V` cannot be known at compilation time
+ --> $DIR/issue-41366.rs:10:8
+ |
+LL | (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
+ | ^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `<u32 as T<'_>>::V`
+ = help: unsized locals are gated as an unstable feature
+help: consider further restricting the associated type
+ |
+LL | fn main() where <u32 as T<'_>>::V: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: function arguments must have a statically known size, borrowed types always have a known size
+ |
+LL | (&|&_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
+ | ^
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0631`.
+Some errors have detailed explanations: E0277, E0631.
+For more information about an error, try `rustc --explain E0277`.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
|
= help: the trait `Iterator` is not implemented for `()`
- = note: the return type of a function must have a statically known size
error: aborting due to previous error
trait _Tr3 {
type A: Iterator<Item: Copy>;
//~^ ERROR associated type bounds are unstable
+ //~| ERROR the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied
type B: Iterator<Item: 'static>;
//~^ ERROR associated type bounds are unstable
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:18:22
+ --> $DIR/feature-gate-associated_type_bounds.rs:19:22
|
LL | type B: Iterator<Item: 'static>;
| ^^^^^^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:22:20
+ --> $DIR/feature-gate-associated_type_bounds.rs:23:20
|
LL | struct _St1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:29:18
+ --> $DIR/feature-gate-associated_type_bounds.rs:30:18
|
LL | enum _En1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:36:19
+ --> $DIR/feature-gate-associated_type_bounds.rs:37:19
|
LL | union _Un1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:43:37
+ --> $DIR/feature-gate-associated_type_bounds.rs:44:37
|
LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
| ^^^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:46:22
+ --> $DIR/feature-gate-associated_type_bounds.rs:47:22
|
LL | fn _apit(_: impl Tr1<As1: Copy>) {}
| ^^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:48:26
+ --> $DIR/feature-gate-associated_type_bounds.rs:49:26
|
LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
| ^^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:51:24
+ --> $DIR/feature-gate-associated_type_bounds.rs:52:24
|
LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
| ^^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:54:31
+ --> $DIR/feature-gate-associated_type_bounds.rs:55:31
|
LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
| ^^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:57:23
+ --> $DIR/feature-gate-associated_type_bounds.rs:58:23
|
LL | const _cdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:63:24
+ --> $DIR/feature-gate-associated_type_bounds.rs:64:24
|
LL | static _sdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:70:21
+ --> $DIR/feature-gate-associated_type_bounds.rs:71:21
|
LL | let _: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
- --> $DIR/feature-gate-associated_type_bounds.rs:57:14
+ --> $DIR/feature-gate-associated_type_bounds.rs:58:14
|
LL | const _cdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^
= help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
- --> $DIR/feature-gate-associated_type_bounds.rs:63:15
+ --> $DIR/feature-gate-associated_type_bounds.rs:64:15
|
LL | static _sdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^
= help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
- --> $DIR/feature-gate-associated_type_bounds.rs:70:12
+ --> $DIR/feature-gate-associated_type_bounds.rs:71:12
|
LL | let _: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
-error: aborting due to 16 previous errors
+error[E0277]: the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied
+ --> $DIR/feature-gate-associated_type_bounds.rs:15:28
+ |
+LL | type A: Iterator<Item: Copy>;
+ | ^^^^ the trait `Copy` is not implemented for `<<Self as _Tr3>::A as Iterator>::Item`
+ |
+ ::: $SRC_DIR/core/src/marker.rs:LL:COL
+ |
+LL | pub trait Copy: Clone {
+ | --------------------- required by this bound in `Copy`
+ |
+help: consider further restricting the associated type
+ |
+LL | trait _Tr3 where <<Self as _Tr3>::A as Iterator>::Item: Copy {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 17 previous errors
-Some errors have detailed explanations: E0562, E0658.
-For more information about an error, try `rustc --explain E0562`.
+Some errors have detailed explanations: E0277, E0562, E0658.
+For more information about an error, try `rustc --explain E0277`.
//~^ ERROR generic associated types are unstable
type Pointer2<U32> = Box<U32>;
//~^ ERROR generic associated types are unstable
+ //~| ERROR the trait bound `U32: Clone` is not satisfied
}
trait Bar {
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error[E0658]: where clauses on associated types are unstable
- --> $DIR/feature-gate-generic_associated_types.rs:21:5
+ --> $DIR/feature-gate-generic_associated_types.rs:22:5
|
LL | type Assoc where Self: Sized;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error[E0658]: where clauses on associated types are unstable
- --> $DIR/feature-gate-generic_associated_types.rs:26:5
+ --> $DIR/feature-gate-generic_associated_types.rs:27:5
|
LL | type Assoc where Self: Sized = Foo;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
-error: aborting due to 7 previous errors
+error[E0277]: the trait bound `U32: Clone` is not satisfied
+ --> $DIR/feature-gate-generic_associated_types.rs:16:5
+ |
+LL | type Pointer2<U32> = Box<U32>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `U32`
+ |
+help: consider restricting type parameter `U32`
+ |
+LL | type Pointer2<U32: Clone> = Box<U32>;
+ | ^^^^^^^
+
+error: aborting due to 8 previous errors
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0277, E0658.
+For more information about an error, try `rustc --explain E0277`.
-// E0277 should point exclusively at line 14, not the entire for loop span
+// E0277 should point exclusively at line 6, not the entire for loop span
fn main() {
for c in "asdf" {
- //~^ ERROR `&str` is not an iterator
- //~| NOTE `&str` is not an iterator
- //~| HELP the trait `Iterator` is not implemented for `&str`
- //~| NOTE required by `into_iter`
- //~| NOTE in this expansion of desugaring of `for` loop
- //~| NOTE in this expansion of desugaring of `for` loop
- //~| NOTE in this expansion of desugaring of `for` loop
+ //~^ ERROR `&str` is not an iterator
+ //~| NOTE `&str` is not an iterator
+ //~| HELP the trait `Iterator` is not implemented for `&str`
+ //~| NOTE required because of the requirements on the impl of `IntoIterator` for `&str`
+ //~| NOTE required by `into_iter`
+ //~| NOTE in this expansion of desugaring of `for` loop
+ //~| NOTE in this expansion of desugaring of `for` loop
+ //~| NOTE in this expansion of desugaring of `for` loop
+ //~| NOTE in this expansion of desugaring of `for` loop
println!();
}
}
| ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
|
= help: the trait `Iterator` is not implemented for `&str`
+ = note: required because of the requirements on the impl of `IntoIterator` for `&str`
= note: required by `into_iter`
error: aborting due to previous error
| ^^^^^ `MyStruct` is not an iterator
|
= help: the trait `Iterator` is not implemented for `MyStruct`
+ = note: required because of the requirements on the impl of `IntoIterator` for `MyStruct`
= note: required by `into_iter`
error: aborting due to previous error
|
LL | Pin::new(&mut gen).resume(());
| ^^^^^^ doesn't have a size known at compile-time
+ |
+ ::: $SRC_DIR/core/src/ops/generator.rs:LL:COL
+ |
+LL | pub enum GeneratorState<Y, R> {
+ | - required by this bound in `GeneratorState`
|
= help: the trait `Sized` is not implemented for `str`
|
= note: expected enum `std::result::Result<{integer}, _>`
found type `i32`
- = note: the return type of a function must have a statically known size
error: aborting due to 2 previous errors
--- /dev/null
+#![feature(generic_associated_types)]
+
+use std::{future::Future, pin::Pin};
+
+pub trait Foo {
+ type Bar: AsRef<()>;
+ fn foo(&self) -> Pin<Box<dyn Future<Output = Self::Bar> + '_>>;
+}
--- /dev/null
+// regression test for #73816
+// We handled bounds differently when `feature(generic_associated_types)` was enabled
+
+// edition:2018
+// aux-build:foo_defn.rs
+
+extern crate foo_defn;
+
+use foo_defn::Foo;
+use std::{future::Future, pin::Pin};
+
+pub struct FooImpl;
+
+impl Foo for FooImpl {
+ type Bar = ();
+ //~^ ERROR the trait bound `(): AsRef<()>` is not satisfied
+ fn foo(&self) -> Pin<Box<dyn Future<Output = Self::Bar> + '_>> {
+ panic!()
+ }
+}
+
+async fn foo() {
+ bar(&FooImpl).await;
+}
+
+async fn bar<F: Foo>(foo: &F) {
+ foo.foo().await.as_ref();
+}
+
+fn main() {
+ // futures::executor::block_on(foo());
+}
--- /dev/null
+error[E0277]: the trait bound `(): AsRef<()>` is not satisfied
+ --> $DIR/cross-crate-bounds.rs:15:5
+ |
+LL | type Bar = ();
+ | ^^^^^^^^^^^^^^ the trait `AsRef<()>` is not implemented for `()`
+ |
+ ::: $DIR/auxiliary/foo_defn.rs:6:15
+ |
+LL | type Bar: AsRef<()>;
+ | --------- required by this bound in `foo_defn::Foo::Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
impl Foo for Bar {
type Assoc = usize;
type Assoc2<T> = Vec<T>;
+ //~^ ERROR `T` doesn't implement `std::fmt::Display`
type Assoc3<T> where T: Iterator = Vec<T>;
- //~^ impl has stricter requirements than trait
+ //~^ ERROR impl has stricter requirements than trait
type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator<Item=T>;
type NoGenerics = ::std::cell::Cell<i32>;
}
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+ --> $DIR/generic-associated-types-where.rs:21:5
+ |
+LL | type Assoc2<T> = Vec<T>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+ |
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+help: consider restricting type parameter `T`
+ |
+LL | type Assoc2<T: std::fmt::Display> = Vec<T>;
+ | ^^^^^^^^^^^^^^^^^^^
+
error[E0276]: impl has stricter requirements than trait
- --> $DIR/generic-associated-types-where.rs:22:5
+ --> $DIR/generic-associated-types-where.rs:23:5
|
LL | type Assoc3<T>;
| --------------- definition of `Assoc3` from trait
LL | type Assoc3<T> where T: Iterator = Vec<T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
-error: aborting due to previous error
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0276`.
+Some errors have detailed explanations: E0276, E0277.
+For more information about an error, try `rustc --explain E0276`.
//~^ ERROR the parameter type `T` may not live long enough
type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
//~^ ERROR lifetime bound not satisfied
+ //~| ERROR lifetime bound not satisfied
type C where Self: Copy = String;
//~^ ERROR the trait bound `T: Copy` is not satisfied
}
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
| ^^
+error[E0478]: lifetime bound not satisfied
+ --> $DIR/impl_bounds.rs:17:5
+ |
+LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 17:12
+ --> $DIR/impl_bounds.rs:17:12
+ |
+LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+ | ^^
+note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 17:16
+ --> $DIR/impl_bounds.rs:17:16
+ |
+LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+ | ^^
+
error[E0277]: the trait bound `T: Copy` is not satisfied
- --> $DIR/impl_bounds.rs:19:5
+ --> $DIR/impl_bounds.rs:20:5
|
LL | type C where Self: Copy = String;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
LL | impl<T: Copy> Foo for Fooy<T> {
| ^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
Some errors have detailed explanations: E0277, E0310, E0478.
For more information about an error, try `rustc --explain E0277`.
type C where Self: Clone;
}
+#[derive(Clone)]
struct Fooy;
impl Foo for Fooy {
type A<'a> = (&'a ());
- type B<'a, 'b> = (&'a(), &'b ());
+ type B<'a: 'b, 'b> = (&'a(), &'b ());
type C = String;
}
impl<T> Foo for Fooer<T> {
type A<'x> where T: 'x = (&'x ());
type B<'u, 'v> where 'u: 'v = (&'v &'u ());
- type C where Self: ToOwned = String;
+ type C where Self: Clone + ToOwned = String;
}
fn main() {}
--> $DIR/issue-68641-check-gat-bounds.rs:15:5
|
LL | type Item<'a>: Copy;
- | -------------------- required by `UnsafeCopy::Item`
+ | ---- required by this bound in `UnsafeCopy::Item`
...
LL | type Item<'a> = T;
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
--> $DIR/issue-68642-broken-llvm-ir.rs:15:5
|
LL | type F<'a>: Fn() -> u32;
- | ------------------------ required by `Fun::F`
+ | ----------- required by this bound in `Fun::F`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
--> $DIR/issue-68643-broken-mir.rs:15:5
|
LL | type F<'a>: Fn() -> u32;
- | ------------------------ required by `Fun::F`
+ | ----------- required by this bound in `Fun::F`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
--> $DIR/issue-68644-codegen-selection.rs:15:5
|
LL | type F<'a>: Fn() -> u32;
- | ------------------------ required by `Fun::F`
+ | ----------- required by this bound in `Fun::F`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
--> $DIR/issue-68645-codegen-fulfillment.rs:15:5
|
LL | type F<'a>: Fn() -> u32;
- | ------------------------ required by `Fun::F`
+ | ----------- required by this bound in `Fun::F`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
--> $DIR/issue-68656-unsized-values.rs:16:5
|
LL | type Item<'a>: std::ops::Deref<Target = T>;
- | ------------------------------------------- required by `UnsafeCopy::Item`
+ | ---------- required by this bound in `UnsafeCopy::Item`
...
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
| - this type parameter
--- /dev/null
+// Like `projection-bound-cycle.rs` but this avoids using
+// `feature(trivial_bounds)`.
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+trait Print {
+ fn print();
+}
+
+trait Foo {
+ type Item: Sized where <Self as Foo>::Item: Sized;
+}
+
+struct Number<T> { t: T }
+
+impl<T> Foo for Number<T> {
+ // Well-formedness checks require that the following
+ // goal is true:
+ // ```
+ // if ([T]: Sized) { # if the where clauses hold
+ // [T]: Sized # then the bound on the associated type hold
+ // }
+ // ```
+ // which it is :)
+ type Item where [T]: Sized = [T];
+}
+
+struct OnlySized<T> where T: Sized { f: T }
+impl<T> Print for OnlySized<T> {
+ fn print() {
+ println!("{}", std::mem::size_of::<T>());
+ }
+}
+
+trait Bar {
+ type Assoc: Print;
+}
+
+impl<T> Bar for T where T: Foo {
+ // This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires
+ // knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We
+ // can use the bound on `Foo::Item` for this, but that requires
+ // `wf(<T as Foo>::Item)`, which is an invalid cycle.
+ type Assoc = OnlySized<<T as Foo>::Item>;
+ //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized`
+}
+
+fn foo<T: Print>() {
+ T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed
+}
+
+fn bar<T: Bar>() {
+ // we have `FromEnv(T: Bar)` hence
+ // `<T as Bar>::Assoc` is well-formed and
+ // `Implemented(<T as Bar>::Assoc: Print)` hold
+ foo::<<T as Bar>::Assoc>()
+}
+
+fn main() {
+ bar::<Number<u8>>()
+}
--- /dev/null
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/projection-bound-cycle-generic.rs:4:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
+ --> $DIR/projection-bound-cycle-generic.rs:45:5
+ |
+LL | struct OnlySized<T> where T: Sized { f: T }
+ | - required by this bound in `OnlySized`
+...
+LL | type Assoc = OnlySized<<T as Foo>::Item>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0275`.
--- /dev/null
+// Test case from Chalk.
+// Make sure that we make sure that we don't allow arbitrary bounds to be
+// proven when a bound and a where clause of an associated type are the same.
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+#![feature(trivial_bounds)]
+
+trait Print {
+ fn print();
+}
+
+trait Foo {
+ type Item: Sized where <Self as Foo>::Item: Sized;
+}
+
+struct Number { }
+
+impl Foo for Number {
+ // Well-formedness checks require that the following
+ // goal is true:
+ // ```
+ // if (str: Sized) { # if the where clauses hold
+ // str: Sized # then the bound on the associated type hold
+ // }
+ // ```
+ // which it is :)
+ type Item where str: Sized = str;
+}
+
+struct OnlySized<T> where T: Sized { f: T }
+impl<T> Print for OnlySized<T> {
+ fn print() {
+ println!("{}", std::mem::size_of::<T>());
+ }
+}
+
+trait Bar {
+ type Assoc: Print;
+}
+
+impl<T> Bar for T where T: Foo {
+ // This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires
+ // knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We
+ // can use the bound on `Foo::Item` for this, but that requires
+ // `wf(<T as Foo>::Item)`, which is an invalid cycle.
+ type Assoc = OnlySized<<T as Foo>::Item>;
+ //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized`
+}
+
+fn foo<T: Print>() {
+ T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed
+}
+
+fn bar<T: Bar>() {
+ // we have `FromEnv(T: Bar)` hence
+ // `<T as Bar>::Assoc` is well-formed and
+ // `Implemented(<T as Bar>::Assoc: Print)` hold
+ foo::<<T as Bar>::Assoc>()
+}
+
+fn main() {
+ bar::<Number>()
+}
--- /dev/null
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/projection-bound-cycle.rs:5:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
+ --> $DIR/projection-bound-cycle.rs:47:5
+ |
+LL | struct OnlySized<T> where T: Sized { f: T }
+ | - required by this bound in `OnlySized`
+...
+LL | type Assoc = OnlySized<<T as Foo>::Item>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0275`.
impl<'b> ATy for &'b () {
type Item<'a> = &'b ();
- //~^ ERROR does not fulfill the required lifetime
+ //~^ ERROR the type `&'b ()` does not fulfill the required lifetime
}
trait StaticTy {
impl StaticTy for () {
type Item<'a> = &'a ();
- //~^ ERROR does not fulfill the required lifetime
+ //~^ ERROR the type `&'a ()` does not fulfill the required lifetime
}
fn main() {}
|
= note: expected type `()`
found associated type `<T as impl_trait::Trait>::Assoc`
- = note: the return type of a function must have a statically known size
help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
|
LL | fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {
|
= note: expected type `()`
found associated type `<T as lifetimes::Trait<'static>>::Assoc`
- = note: the return type of a function must have a statically known size
help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
|
LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {
| ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
|
= note: required because it appears within the type `(S, T)`
- = note: the return type of a function must have a statically known size
help: consider further restricting this bound
|
LL | impl<S: Default + Copy> Bar for S {
| ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
|
= note: required because it appears within the type `(S, T)`
- = note: the return type of a function must have a statically known size
help: consider further restricting this bound
|
LL | fn foo<T: Default + Copy>() -> Self::E {
|
LL | type E = impl std::marker::Copy;
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future`
- |
- = note: the return type of a function must have a statically known size
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> $DIR/issue-55872-2.rs:15:28
--- /dev/null
+// Check that we handle evaluating `wf` predicates correctly.
+
+// check-pass
+
+struct X<T: B>(T)
+where
+ T::V: Clone;
+
+fn hide<T>(t: T) -> impl Sized {
+ t
+}
+
+trait A {
+ type U;
+}
+
+impl<T> A for T {
+ type U = T;
+}
+
+trait B {
+ type V;
+}
+
+impl<S: A<U = T>, T> B for S {
+ type V = T;
+}
+
+fn main() {
+ // Evaluating `typeof(x): Sized` requires
+ //
+ // - `wf(typeof(x))` because we use a projection candidate.
+ // - `<i32 as B>::V: Clone` because that's a bound on the trait.
+ // - `<i32 as B>::V` normalizes to `_#1` where `<i32 as A>::U == _#1`
+ //
+ // This all works if we evaluate `<i32 as A>::U == _#1` before
+ // `<i32 as B>::V`, but we previously had the opposite order.
+ let x = hide(X(0));
+}
= note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
error[E0282]: type annotations needed for `impl Future`
- --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:9
+ --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20
|
LL | let fut = async {
| --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified
LL | make_unit()?;
- | ^^^^^^^^^^^^ cannot infer type
+ | ^ cannot infer type
error: aborting due to previous error; 1 warning emitted
error[E0282]: type annotations needed
- --> $DIR/cannot-infer-async.rs:11:9
+ --> $DIR/cannot-infer-async.rs:11:20
|
LL | let fut = async {
| --- consider giving `fut` a type
LL | make_unit()?;
- | ^^^^^^^^^^^^ cannot infer type
+ | ^ cannot infer type
error: aborting due to previous error
error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>`
- --> $DIR/cannot-infer-closure.rs:3:9
+ --> $DIR/cannot-infer-closure.rs:3:15
|
LL | Err(a)?;
- | ^^^^^^^ cannot infer type
+ | ^ cannot infer type
|
help: give this closure an explicit return type without `_` placeholders
|
|
LL | fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future
-LL | *x
- | -- this returned value is of type `u32`
|
= help: the trait `Future` is not implemented for `u32`
- = note: the return type of a function must have a statically known size
error: aborting due to 2 previous errors
| ^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
+ = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator<Item = &'a mut u8>`
= note: required by `into_iter`
error: aborting due to previous error
fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
// Not obvious, but there is an implicit lifetime here -------^
//~^^ ERROR cannot infer
- //~| ERROR cannot infer
- //~| ERROR mismatched types
- //~| ERROR mismatched types
//
// The fact that `Publisher` is using an implicit lifetime is
// what was causing the debruijn accounting to be off, so
-error[E0308]: mismatched types
- --> $DIR/issue-20831-debruijn.rs:28:5
- |
-LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | | // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |
-... |
-LL | | self.sub = t;
-LL | | }
- | |_____^ lifetime mismatch
- |
- = note: expected type `'a`
- found type `'_`
-note: the anonymous lifetime #2 defined on the method body at 28:5...
- --> $DIR/issue-20831-debruijn.rs:28:5
- |
-LL | fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 26:6
- --> $DIR/issue-20831-debruijn.rs:26:6
- |
-LL | impl<'a> Publisher<'a> for MyStruct<'a> {
- | ^^
-
-error[E0308]: mismatched types
- --> $DIR/issue-20831-debruijn.rs:28:5
- |
-LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | | // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |
-... |
-LL | | self.sub = t;
-LL | | }
- | |_____^ lifetime mismatch
- |
- = note: expected type `'a`
- found type `'_`
-note: the lifetime `'a` as defined on the impl at 26:6...
- --> $DIR/issue-20831-debruijn.rs:26:6
- |
-LL | impl<'a> Publisher<'a> for MyStruct<'a> {
- | ^^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 28:5
- --> $DIR/issue-20831-debruijn.rs:28:5
- |
-LL | fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
- --> $DIR/issue-20831-debruijn.rs:28:33
- |
-LL | fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5...
- --> $DIR/issue-20831-debruijn.rs:28:5
- |
-LL | fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6...
- --> $DIR/issue-20831-debruijn.rs:26:6
- |
-LL | impl<'a> Publisher<'a> for MyStruct<'a> {
- | ^^
-note: ...so that the types are compatible
- --> $DIR/issue-20831-debruijn.rs:28:33
- |
-LL | fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: expected `Publisher<'_>`
- found `Publisher<'_>`
-
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> $DIR/issue-20831-debruijn.rs:28:33
|
= note: expected `Publisher<'_>`
found `Publisher<'_>`
-error: aborting due to 4 previous errors
+error: aborting due to previous error
-Some errors have detailed explanations: E0308, E0495.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0495`.
struct FooStruct;
impl Foo for FooStruct {
- //~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A == _`
type A = <FooStruct as Foo>::A;
//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A == _`
}
error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A == _`
- --> $DIR/issue-21946.rs:7:6
- |
-LL | impl Foo for FooStruct {
- | ^^^
-
-error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A == _`
- --> $DIR/issue-21946.rs:9:5
+ --> $DIR/issue-21946.rs:8:5
|
LL | type A = <FooStruct as Foo>::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0275`.
struct GetNext<T: Next> { t: T }
impl<T: Next> Next for GetNext<T> {
- //~^ ERROR overflow evaluating the requirement
type Next = <GetNext<T> as Next>::Next;
//~^ ERROR overflow evaluating the requirement
}
error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next == _`
- --> $DIR/issue-23122-1.rs:7:15
- |
-LL | impl<T: Next> Next for GetNext<T> {
- | ^^^^
-
-error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next == _`
- --> $DIR/issue-23122-1.rs:9:5
+ --> $DIR/issue-23122-1.rs:8:5
|
LL | type Next = <GetNext<T> as Next>::Next;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0275`.
struct GetNext<T: Next> { t: T }
impl<T: Next> Next for GetNext<T> {
- //~^ ERROR overflow evaluating the requirement
type Next = <GetNext<T::Next> as Next>::Next;
//~^ ERROR overflow evaluating the requirement
}
-error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
- --> $DIR/issue-23122-2.rs:7:15
- |
-LL | impl<T: Next> Next for GetNext<T> {
- | ^^^^
- |
- = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
- = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
-
error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
- --> $DIR/issue-23122-2.rs:9:5
+ --> $DIR/issue-23122-2.rs:8:5
|
LL | type Next = <GetNext<T::Next> as Next>::Next;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
= note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0275`.
+// check-pass
+
#![allow(dead_code)]
trait MultiDispatch<T> {
type A: MultiDispatch<Self::B, O = Self>;
type B;
- fn new<U>(u: U) -> <Self::A as MultiDispatch<U>>::O where Self::A : MultiDispatch<U>;
+ fn new<U>(u: U) -> <Self::A as MultiDispatch<U>>::O
+ where
+ Self::A: MultiDispatch<U>;
}
-fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::new(b) }
-//~^ ERROR type mismatch resolving
+fn test<T: Trait<B = i32>>(b: i32) -> T
+where
+ T::A: MultiDispatch<i32>,
+{
+ T::new(b)
+}
fn main() {}
+++ /dev/null
-error[E0271]: type mismatch resolving `<<T as Trait>::A as MultiDispatch<i32>>::O == T`
- --> $DIR/issue-24204.rs:14:12
- |
-LL | trait Trait: Sized {
- | ----- required by a bound in this
-LL | type A: MultiDispatch<Self::B, O = Self>;
- | -------- required by this bound in `Trait`
-...
-LL | fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::new(b) }
- | - ^^^^^^^^^^^^ expected type parameter `T`, found associated type
- | |
- | this type parameter
- |
- = note: expected type parameter `T`
- found associated type `<<T as Trait>::A as MultiDispatch<i32>>::O`
- = note: you might be missing a type parameter or trait bound
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0271`.
| ^^^^^ `bool` is not an iterator
|
= help: the trait `Iterator` is not implemented for `bool`
+ = note: required because of the requirements on the impl of `IntoIterator` for `bool`
= note: required by `into_iter`
error[E0277]: `()` is not an iterator
| ^^^^^ `bool` is not an iterator
|
= help: the trait `Iterator` is not implemented for `bool`
+ = note: required because of the requirements on the impl of `IntoIterator` for `bool`
= note: required by `into_iter`
error[E0277]: `()` is not an iterator
= note: expected tuple `(&_, &_)`
found reference `&_`
= note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+ = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+ = note: required by `into_iter`
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
--> $DIR/issue-33941.rs:4:14
= note: expected tuple `(&_, &_)`
found reference `&_`
= note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+ = note: required by `std::iter::Iterator::next`
error: aborting due to 3 previous errors
+++ /dev/null
-#![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
-
-trait Iterate<'a> {
- type Ty: Valid;
- fn iterate(self);
-}
-impl<'a, T> Iterate<'a> for T where T: Check {
- default type Ty = ();
- //~^ ERROR the trait bound `(): Valid` is not satisfied
- default fn iterate(self) {}
-}
-
-trait Check {}
-impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
-
-trait Valid {}
-
-fn main() {
- Iterate::iterate(0);
-}
+++ /dev/null
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/issue-38091.rs:1:12
- |
-LL | #![feature(specialization)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-
-error[E0277]: the trait bound `(): Valid` is not satisfied
- --> $DIR/issue-38091.rs:9:5
- |
-LL | type Ty: Valid;
- | --------------- required by `Iterate::Ty`
-...
-LL | default type Ty = ();
- | ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()`
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
trait Trait {}
-fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { panic!("") }
+fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait {
+ panic!("")
+}
fn main() {
- let t : &dyn Trait = &get_function()();
- //~^ ERROR cannot move a value of type dyn Trait
+ // This isn't great. The issue here is that `dyn Trait` is not sized, so
+ // `dyn Fn() -> dyn Trait` is not well-formed.
+ let t: &dyn Trait = &get_function()();
+ //~^ ERROR expected function, found `&dyn Fn() -> (dyn Trait + 'static)`
}
-error[E0161]: cannot move a value of type dyn Trait: the size of dyn Trait cannot be statically determined
- --> $DIR/issue-41139.rs:6:27
+error[E0618]: expected function, found `&dyn Fn() -> (dyn Trait + 'static)`
+ --> $DIR/issue-41139.rs:10:26
|
-LL | let t : &dyn Trait = &get_function()();
- | ^^^^^^^^^^^^^^^^
+LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait {
+ | -------------------------------------------------- `get_function` defined here returns `&dyn Fn() -> (dyn Trait + 'static)`
+...
+LL | let t: &dyn Trait = &get_function()();
+ | ^^^^^^^^^^^^^^--
+ | |
+ | call expression requires function
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0161`.
+For more information about this error, try `rustc --explain E0618`.
error[E0277]: the trait bound `T: Copy` is not satisfied
- --> $DIR/issue-43784-associated-type.rs:14:18
+ --> $DIR/issue-43784-associated-type.rs:14:5
|
+LL | type Assoc: Partial<Self>;
+ | ------------- required by this bound in `Complete::Assoc`
+...
LL | type Assoc = T;
- | ^ the trait `Copy` is not implemented for `T`
+ | ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
error[E0277]: the trait bound `T: Copy` is not satisfied
--> $DIR/issue-43784-supertrait.rs:8:9
|
+LL | pub trait Complete: Partial {
+ | ------- required by this bound in `Complete`
+...
LL | impl<T> Complete for T {}
| ^^^^^^^^ the trait `Copy` is not implemented for `T`
|
+// check-pass
+
use std::ops::Add;
trait Trait<T> {
}
impl<L, R> Either<L, R> {
- fn converge<T>(self) -> T where L: Trait<T>, R: Trait<T> {
+ fn converge<T>(self) -> T
+ where
+ L: Trait<T>,
+ R: Trait<T>,
+ {
match self {
Either::Left(val) => val.get(),
Either::Right(val) => val.get(),
}
}
-fn add_generic<A: Add<B>, B>(lhs: A, rhs: B) -> Either<
- impl Trait<<A as Add<B>>::Output>,
- impl Trait<<A as Add<B>>::Output>
-> {
- if true {
- Either::Left(Holder(lhs + rhs))
- } else {
- Either::Right(Holder(lhs + rhs))
- }
+fn add_generic<A: Add<B>, B>(
+ lhs: A,
+ rhs: B,
+) -> Either<impl Trait<<A as Add<B>>::Output>, impl Trait<<A as Add<B>>::Output>> {
+ if true { Either::Left(Holder(lhs + rhs)) } else { Either::Right(Holder(lhs + rhs)) }
}
fn add_one(
value: u32,
) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
- //~^ ERROR: the trait bound `impl Trait<<u32 as Add>::Output>: Trait<u32>`
- //~| ERROR: the trait bound `impl Trait<<u32 as Add>::Output>: Trait<u32>`
add_generic(value, 1u32)
}
+++ /dev/null
-error[E0277]: the trait bound `impl Trait<<u32 as Add>::Output>: Trait<u32>` is not satisfied
- --> $DIR/issue-58344.rs:42:13
- |
-LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as Add>::Output>`
-...
-LL | add_generic(value, 1u32)
- | ------------------------ this returned value is of type `Either<impl Trait<<u32 as Add>::Output>, impl Trait<<u32 as Add>::Output>>`
- |
- = note: the return type of a function must have a statically known size
-
-error[E0277]: the trait bound `impl Trait<<u32 as Add>::Output>: Trait<u32>` is not satisfied
- --> $DIR/issue-58344.rs:42:52
- |
-LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as Add>::Output>`
-...
-LL | add_generic(value, 1u32)
- | ------------------------ this returned value is of type `Either<impl Trait<<u32 as Add>::Output>, impl Trait<<u32 as Add>::Output>>`
- |
- = note: the return type of a function must have a statically known size
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
fn main() {
foo((), drop)
//~^ ERROR type mismatch in function arguments
+ //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
}
| expected signature of `fn(<() as Trait<'a>>::Item) -> _`
| found signature of `fn(()) -> _`
-error: aborting due to previous error
+error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
+ --> $DIR/issue-60283.rs:17:13
+ |
+LL | foo((), drop)
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
+ |
+LL | pub fn drop<T>(_x: T) {}
+ | - required by this bound in `std::mem::drop`
+ |
+ = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
+help: consider further restricting the associated type
+ |
+LL | fn main() where <() as Trait<'_>>::Item: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0631`.
+Some errors have detailed explanations: E0277, E0631.
+For more information about an error, try `rustc --explain E0277`.
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
- --> $DIR/issue-65673.rs:9:16
+ --> $DIR/issue-65673.rs:9:5
|
-LL | trait WithType {
- | -------- required by a bound in this
LL | type Ctx;
- | --------- required by this bound in `WithType`
+ | --------- required by this bound in `WithType::Ctx`
...
LL | type Ctx = dyn Alias<T>;
- | ^^^^^^^^^^^^ doesn't have a size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Trait + 'static)`
|
= help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]`
= note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]`
= note: required by `into_iter`
error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]`
= note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]`
= note: required by `into_iter`
error[E0277]: `[RangeFrom<{integer}>; 1]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[RangeFrom<{integer}>; 1]`
= note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[RangeFrom<{integer}>; 1]`
= note: required by `into_iter`
error[E0277]: `[RangeTo<{integer}>; 1]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[RangeTo<{integer}>; 1]`
= note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[RangeTo<{integer}>; 1]`
= note: required by `into_iter`
error[E0277]: `[RangeToInclusive<{integer}>; 1]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[RangeToInclusive<{integer}>; 1]`
= note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[RangeToInclusive<{integer}>; 1]`
= note: required by `into_iter`
error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]`
= note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]`
= note: required by `into_iter`
error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]`
= note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]`
= note: required by `into_iter`
error[E0277]: `[std::ops::Range<{integer}>; 2]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]`
= note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 2]`
= note: required by `into_iter`
error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]`
= note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]`
= note: required by `into_iter`
error: aborting due to 9 previous errors
|
= help: the trait `Iterator` is not implemented for `[{integer}; 2]`
= note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]`
= note: required by `into_iter`
error[E0277]: `[{integer}; 2]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[{integer}; 2]`
= note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]`
= note: required by `into_iter`
error[E0277]: `[{float}; 2]` is not an iterator
|
= help: the trait `Iterator` is not implemented for `[{float}; 2]`
= note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+ = note: required because of the requirements on the impl of `IntoIterator` for `[{float}; 2]`
= note: required by `into_iter`
error: aborting due to 3 previous errors
|
= help: the trait `Iterator` is not implemented for `{integer}`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `{integer}`
= note: required by `into_iter`
error[E0277]: `u8` is not an iterator
|
= help: the trait `Iterator` is not implemented for `u8`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `u8`
= note: required by `into_iter`
error[E0277]: `i8` is not an iterator
|
= help: the trait `Iterator` is not implemented for `i8`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `i8`
= note: required by `into_iter`
error[E0277]: `u16` is not an iterator
|
= help: the trait `Iterator` is not implemented for `u16`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `u16`
= note: required by `into_iter`
error[E0277]: `i16` is not an iterator
|
= help: the trait `Iterator` is not implemented for `i16`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `i16`
= note: required by `into_iter`
error[E0277]: `u32` is not an iterator
|
= help: the trait `Iterator` is not implemented for `u32`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `u32`
= note: required by `into_iter`
error[E0277]: `i32` is not an iterator
|
= help: the trait `Iterator` is not implemented for `i32`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `i32`
= note: required by `into_iter`
error[E0277]: `u64` is not an iterator
|
= help: the trait `Iterator` is not implemented for `u64`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `u64`
= note: required by `into_iter`
error[E0277]: `i64` is not an iterator
|
= help: the trait `Iterator` is not implemented for `i64`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `i64`
= note: required by `into_iter`
error[E0277]: `usize` is not an iterator
|
= help: the trait `Iterator` is not implemented for `usize`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `usize`
= note: required by `into_iter`
error[E0277]: `isize` is not an iterator
|
= help: the trait `Iterator` is not implemented for `isize`
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+ = note: required because of the requirements on the impl of `IntoIterator` for `isize`
= note: required by `into_iter`
error[E0277]: `{float}` is not an iterator
| ^^^^ `{float}` is not an iterator
|
= help: the trait `Iterator` is not implemented for `{float}`
+ = note: required because of the requirements on the impl of `IntoIterator` for `{float}`
= note: required by `into_iter`
error: aborting due to 12 previous errors
| ^^^^ `RangeTo<{integer}>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `RangeTo<{integer}>`
+ = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>`
= note: required by `into_iter`
error[E0277]: `RangeToInclusive<{integer}>` is not an iterator
| ^^^^^ `RangeToInclusive<{integer}>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`
+ = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>`
= note: required by `into_iter`
error: aborting due to 2 previous errors
| ^^^^^^^^^^^^^ `String` is not an iterator
|
= help: the trait `Iterator` is not implemented for `String`
+ = note: required because of the requirements on the impl of `IntoIterator` for `String`
= note: required by `into_iter`
error[E0277]: `&str` is not an iterator
| ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
|
= help: the trait `Iterator` is not implemented for `&str`
+ = note: required because of the requirements on the impl of `IntoIterator` for `&str`
= note: required by `into_iter`
error: aborting due to 2 previous errors
|
LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>`
-LL |
-LL | Ok(())
- | ------ this returned value is of type `std::result::Result<(), _>`
- |
- = note: the return type of a function must have a statically known size
error: aborting due to previous error
|
LL | fn should_ret_unit() -> impl T {
| ^^^^^^ the trait `T` is not implemented for `()`
-LL |
-LL | panic!()
- | -------- this returned value is of type `!`
- |
- = note: the return type of a function must have a statically known size
error: aborting due to previous error
--> $DIR/issue-51506.rs:13:5
|
LL | type Out: Iterator<Item = u32>;
- | ------------------------------- required by `Trait::Out`
+ | -------------------- required by this bound in `Trait::Out`
...
LL | default type Out = !;
| ^^^^^^^^^^^^^^^^^^^^^ `!` is not an iterator
let _x = <fn(&())>::make_f();
//~^ higher-ranked subtype error
//~| higher-ranked subtype error
- //~| higher-ranked subtype error
}
LL | let _x = <fn(&())>::make_f();
| ^^^^^^^^^^^^^^^^^^^
-error: higher-ranked subtype error
- --> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14
- |
-LL | let _x = <fn(&())>::make_f();
- | ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
--- /dev/null
+// Traits with bounds mentioning `Self` are not object safe
+
+trait X {
+ type U: PartialEq<Self>;
+}
+
+fn f() -> Box<dyn X<U = u32>> {
+ //~^ ERROR the trait `X` cannot be made into an object
+ loop {}
+}
+
+fn main() {}
--- /dev/null
+error[E0038]: the trait `X` cannot be made into an object
+ --> $DIR/object-safety-bounds.rs:7:11
+ |
+LL | trait X {
+ | - this trait cannot be made into an object...
+LL | type U: PartialEq<Self>;
+ | --------------- ...because it uses `Self` as a type parameter in this
+...
+LL | fn f() -> Box<dyn X<U = u32>> {
+ | ^^^^^^^^^^^^^^^^^^^ the trait `X` cannot be made into an object
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
| |__________^ `bool` is not an iterator
|
= help: the trait `Iterator` is not implemented for `bool`
+ = note: required because of the requirements on the impl of `IntoIterator` for `bool`
= note: required by `into_iter`
error: aborting due to 2 previous errors
// "Private-in-public in associated types is hard error" in RFC 2145
// applies only to the aliased types, not bounds.
pub trait PubTr {
+ type Alias1: PrivTr;
//~^ WARN private trait `PrivTr` in public interface
//~| WARN this was previously accepted
- //~| WARN private type `Priv` in public interface
- //~| WARN private type `Priv` in public interface
- //~| WARN this was previously accepted
- //~| WARN this was previously accepted
- type Alias1: PrivTr;
type Alias2: PubTrAux1<Priv> = u8;
+ //~^ WARN private type `Priv` in public interface
+ //~| WARN this was previously accepted
type Alias3: PubTrAux2<A = Priv> = u8;
+ //~^ WARN private type `Priv` in public interface
+ //~| WARN this was previously accepted
type Alias4 = Priv;
//~^ ERROR private type `Priv` in public interface
| ^^^^^^^^^^^^^^ can't leak private type
warning: private trait `PrivTr` in public interface (error E0445)
- --> $DIR/private-in-public-assoc-ty.rs:23:5
+ --> $DIR/private-in-public-assoc-ty.rs:24:9
|
-LL | / pub trait PubTr {
-LL | |
-LL | |
-LL | |
-... |
-LL | | fn infer_exist() -> Self::Exist;
-LL | | }
- | |_____^
+LL | type Alias1: PrivTr;
+ | ^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(private_in_public)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
warning: private type `Priv` in public interface (error E0446)
- --> $DIR/private-in-public-assoc-ty.rs:23:5
+ --> $DIR/private-in-public-assoc-ty.rs:27:9
|
-LL | / pub trait PubTr {
-LL | |
-LL | |
-LL | |
-... |
-LL | | fn infer_exist() -> Self::Exist;
-LL | | }
- | |_____^
+LL | type Alias2: PubTrAux1<Priv> = u8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
warning: private type `Priv` in public interface (error E0446)
- --> $DIR/private-in-public-assoc-ty.rs:23:5
+ --> $DIR/private-in-public-assoc-ty.rs:30:9
|
-LL | / pub trait PubTr {
-LL | |
-LL | |
-LL | |
-... |
-LL | | fn infer_exist() -> Self::Exist;
-LL | | }
- | |_____^
+LL | type Alias3: PubTrAux2<A = Priv> = u8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
pub trait Tr2<T: PrivTr> {} //~ ERROR private trait `traits::PrivTr` in public interface
//~^ WARNING hard error
pub trait Tr3 {
+ type Alias: PrivTr;
//~^ ERROR private trait `traits::PrivTr` in public interface
//~| WARNING hard error
- type Alias: PrivTr;
fn f<T: PrivTr>(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface
//~^ WARNING hard error
}
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
error: private trait `traits::PrivTr` in public interface (error E0445)
- --> $DIR/private-in-public-warn.rs:57:5
- |
-LL | / pub trait Tr3 {
-LL | |
-LL | |
-LL | | type Alias: PrivTr;
-LL | | fn f<T: PrivTr>(arg: T) {}
-LL | |
-LL | | }
- | |_____^
+ --> $DIR/private-in-public-warn.rs:58:9
+ |
+LL | type Alias: PrivTr;
+ | ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
- // aux-crate:priv:priv_dep=priv_dep.rs
- // aux-build:pub_dep.rs
+// aux-crate:priv:priv_dep=priv_dep.rs
+// aux-build:pub_dep.rs
#![deny(exported_private_dependencies)]
// This crate is a private dependency
// This crate is a public dependency
extern crate pub_dep;
-use priv_dep::{OtherType, OtherTrait};
+use priv_dep::{OtherTrait, OtherType};
use pub_dep::PubType;
// Type from private dependency used in private
// type - this is fine
struct PrivateType {
- field: OtherType
+ field: OtherType,
}
pub struct PublicType {
pub field: OtherType,
//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
- priv_field: OtherType, // Private field - this is fine
- pub other_field: PubType // Type from public dependency - this is fine
+ priv_field: OtherType, // Private field - this is fine
+ pub other_field: PubType, // Type from public dependency - this is fine
}
impl PublicType {
pub trait MyPubTrait {
type Foo: OtherTrait;
}
-//~^^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
+//~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
pub struct AllowedPrivType {
#[allow(exported_private_dependencies)]
- pub allowed: OtherType
+ pub allowed: OtherType,
}
-
-
fn main() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:33:1
+ --> $DIR/pub-priv1.rs:34:5
|
-LL | / pub trait MyPubTrait {
-LL | | type Foo: OtherTrait;
-LL | | }
- | |_^
+LL | type Foo: OtherTrait;
+ | ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
-error[E0284]: type annotations needed
+error[E0283]: type annotations needed
--> $DIR/question-mark-type-infer.rs:12:21
|
LL | l.iter().map(f).collect()?
| ^^^^^^^ cannot infer type
|
- = note: cannot satisfy `<_ as Try>::Ok == _`
+ = note: cannot satisfy `_: Try`
+ = note: required by `into_result`
help: consider specifying the type argument in the method call
|
LL | l.iter().map(f).collect::<B>()?
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0283`.
| ^^^^^^^^^^^ the trait `Step` is not implemented for `bool`
|
= note: required because of the requirements on the impl of `Iterator` for `std::ops::Range<bool>`
+ = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range<bool>`
+ = note: required by `into_iter`
error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
--> $DIR/range-1.rs:14:17
trait Foo<'a> {
type Value: 'a;
- fn dummy(&'a self) { }
+ fn dummy(&'a self) {}
}
impl<'a> Foo<'a> for &'a i16 {
}
impl<'a> Foo<'static> for &'a i32 {
- //~^ ERROR cannot infer
type Value = &'a i32;
+ //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
}
-impl<'a,'b> Foo<'b> for &'a i64 {
- //~^ ERROR cannot infer
+impl<'a, 'b> Foo<'b> for &'a i64 {
type Value = &'a i32;
+ //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
}
-fn main() { }
+fn main() {}
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
- --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+ --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:15:5
|
-LL | impl<'a> Foo<'static> for &'a i32 {
- | ^^^^^^^^^^^^
+LL | type Value = &'a i32;
+ | ^^^^^^^^^^^^^^^^^^^^^
|
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 14:6...
- --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6
- |
-LL | impl<'a> Foo<'static> for &'a i32 {
- | ^^
-note: ...so that the types are compatible
- --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
- |
-LL | impl<'a> Foo<'static> for &'a i32 {
- | ^^^^^^^^^^^^
- = note: expected `Foo<'static>`
- found `Foo<'static>`
- = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the type `&i32` will meet its required lifetime bounds
- --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
- |
-LL | impl<'a> Foo<'static> for &'a i32 {
- | ^^^^^^^^^^^^
+ = note: type must satisfy the static lifetime
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
- --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
- |
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
- | ^^^^^^^
- |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 19:6...
- --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6
- |
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
- | ^^
-note: ...so that the types are compatible
- --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+ --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:20:5
|
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
- | ^^^^^^^
- = note: expected `Foo<'b>`
- found `Foo<'_>`
-note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9...
- --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9
+LL | type Value = &'a i32;
+ | ^^^^^^^^^^^^^^^^^^^^^
|
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
- | ^^
-note: ...so that the type `&i32` will meet its required lifetime bounds
- --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
+note: type must outlive the lifetime `'b` as defined on the impl at 19:10
+ --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:10
|
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
- | ^^^^^^^
+LL | impl<'a, 'b> Foo<'b> for &'a i64 {
+ | ^^
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0477`.
trait Foo {
type Value: 'static;
- fn dummy(&self) { }
+ fn dummy(&self) {}
}
impl<'a> Foo for &'a i32 {
- //~^ ERROR cannot infer
type Value = &'a i32;
+ //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
}
impl<'a> Foo for i32 {
type Value = i32;
}
-fn main() { }
+fn main() {}
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
- --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+ --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:10:5
|
-LL | impl<'a> Foo for &'a i32 {
- | ^^^
+LL | type Value = &'a i32;
+ | ^^^^^^^^^^^^^^^^^^^^^
|
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 9:6...
- --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6
- |
-LL | impl<'a> Foo for &'a i32 {
- | ^^
-note: ...so that the types are compatible
- --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
- |
-LL | impl<'a> Foo for &'a i32 {
- | ^^^
- = note: expected `Foo`
- found `Foo`
- = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the type `&i32` will meet its required lifetime bounds
- --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
- |
-LL | impl<'a> Foo for &'a i32 {
- | ^^^
+ = note: type must satisfy the static lifetime
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0477`.
#![allow(dead_code)]
trait Dummy<'a> {
- type Out;
+ type Out;
}
impl<'a, T> Dummy<'a> for T
-where T: 'a
+where
+ T: 'a,
{
- type Out = ();
+ type Out = ();
}
type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
enum Ref1<'a, T> {
- Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough
+ Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
}
enum Ref2<'a, T> {
Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
}
-enum RefOk<'a, T:'a> {
- RefOkVariant1(&'a T)
+enum RefOk<'a, T: 'a> {
+ RefOkVariant1(&'a T),
}
// This is now well formed. RFC 2093
enum RefIndirect<'a, T> {
- RefIndirectVariant1(isize, RefOk<'a,T>)
+ RefIndirectVariant1(isize, RefOk<'a, T>),
}
-enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309]
- RefDoubleVariant1(&'a RequireOutlives<'b, T>)
- //~^ the parameter type `T` may not live long enough [E0309]
+enum RefDouble<'a, 'b, T> {
+ RefDoubleVariant1(&'a RequireOutlives<'b, T>),
+ //~^ the parameter type `T` may not live long enough [E0309]
}
-fn main() { }
+fn main() {}
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:18:18
+ --> $DIR/regions-enum-not-wf.rs:19:18
|
LL | enum Ref1<'a, T> {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL | Ref1Variant1(RequireOutlives<'a, T>)
+LL | Ref1Variant1(RequireOutlives<'a, T>),
| ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:23:25
+ --> $DIR/regions-enum-not-wf.rs:24:25
|
LL | enum Ref2<'a, T> {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
| ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:35:1
- |
-LL | enum RefDouble<'a, 'b, T> {
- | ^ - help: consider adding an explicit lifetime bound...: `T: 'b`
- | _|
- | |
-LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-LL | |
-LL | | }
- | |_^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:36:23
+ --> $DIR/regions-enum-not-wf.rs:37:23
|
LL | enum RefDouble<'a, 'b, T> {
| - help: consider adding an explicit lifetime bound...: `T: 'b`
-LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0309`.
}
impl<'a, 'b> Project<'a, 'b> for ()
- where 'a: 'b
+where
+ 'a: 'b,
{
type Item = ();
}
// No error here, we have 'a: 'b. We used to report an error here
// though, see https://github.com/rust-lang/rust/issues/45937.
fn foo<'a: 'b, 'b>()
- where <() as Project<'a, 'b>>::Item : Eq
+where
+ <() as Project<'a, 'b>>::Item: Eq,
{
}
// Here we get an error: we need `'a: 'b`.
-fn bar<'a, 'b>() //~ ERROR cannot infer
- //~| ERROR cannot infer
- //~| ERROR cannot infer
- where <() as Project<'a, 'b>>::Item : Eq
+fn bar<'a, 'b>()
+//~^ ERROR cannot infer
+//~| ERROR cannot infer
+where
+ <() as Project<'a, 'b>>::Item: Eq,
{
}
-fn main() { }
+fn main() {}
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:1
|
LL | / fn bar<'a, 'b>()
LL | |
LL | |
-LL | | where <() as Project<'a, 'b>>::Item : Eq
- | |____________________________________________^
+LL | | where
+LL | | <() as Project<'a, 'b>>::Item: Eq,
+ | |______________________________________^
|
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8...
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:8
|
LL | fn bar<'a, 'b>()
| ^^
-note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12...
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:12
|
LL | fn bar<'a, 'b>()
| ^^
note: ...so that the types are compatible
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:1
|
LL | / fn bar<'a, 'b>()
LL | |
LL | |
-LL | | where <() as Project<'a, 'b>>::Item : Eq
- | |____________________________________________^
+LL | | where
+LL | | <() as Project<'a, 'b>>::Item: Eq,
+ | |______________________________________^
= note: expected `Project<'a, 'b>`
found `Project<'_, '_>`
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
- |
-LL | / fn bar<'a, 'b>()
-LL | |
-LL | |
-LL | | where <() as Project<'a, 'b>>::Item : Eq
- | |____________________________________________^
- |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
- |
-LL | fn bar<'a, 'b>()
- | ^^
-note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
- |
-LL | fn bar<'a, 'b>()
- | ^^
-note: ...so that the types are compatible
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
- |
-LL | / fn bar<'a, 'b>()
-LL | |
-LL | |
-LL | | where <() as Project<'a, 'b>>::Item : Eq
- | |____________________________________________^
- = note: expected `Project<'a, 'b>`
- found `Project<'_, '_>`
-
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:4
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:4
|
LL | fn bar<'a, 'b>()
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8...
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:8
|
LL | fn bar<'a, 'b>()
| ^^
-note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12...
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:12
|
LL | fn bar<'a, 'b>()
| ^^
note: ...so that the types are compatible
- --> $DIR/regions-normalize-in-where-clause-list.rs:22:4
+ --> $DIR/regions-normalize-in-where-clause-list.rs:24:4
|
LL | fn bar<'a, 'b>()
| ^^^
= note: expected `Project<'a, 'b>`
found `Project<'_, '_>`
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0495`.
-#![feature(box_syntax)]
+// check-pass
-struct Ctxt { v: usize }
+struct Ctxt {
+ v: usize,
+}
trait GetCtxt {
// Here the `&` is bound in the method definition:
fn get_ctxt(&self) -> &Ctxt;
}
-struct HasCtxt<'a> { c: &'a Ctxt }
+struct HasCtxt<'a> {
+ c: &'a Ctxt,
+}
impl<'a> GetCtxt for HasCtxt<'a> {
-
- // Here an error occurs because we used `&self` but
- // the definition used `&`:
- fn get_ctxt(&self) -> &'a Ctxt { //~ ERROR method not compatible with trait
+ // Ok: Have implied bound of WF(&'b HasCtxt<'a>)
+ // so know 'a: 'b
+ // so know &'a Ctxt <: &'b Ctxt
+ fn get_ctxt<'b>(&'b self) -> &'a Ctxt {
self.c
}
-
}
-fn get_v(gc: Box<dyn GetCtxt>) -> usize {
+fn get_v(gc: Box<dyn GetCtxt + '_>) -> usize {
gc.get_ctxt().v
}
fn main() {
let ctxt = Ctxt { v: 22 };
let hc = HasCtxt { c: &ctxt };
- assert_eq!(get_v(box hc as Box<dyn GetCtxt>), 22);
+ assert_eq!(get_v(Box::new(hc) as Box<dyn GetCtxt>), 22);
}
+++ /dev/null
-error[E0308]: method not compatible with trait
- --> $DIR/regions-trait-1.rs:16:5
- |
-LL | fn get_ctxt(&self) -> &'a Ctxt {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
- |
- = note: expected fn pointer `fn(&HasCtxt<'a>) -> &Ctxt`
- found fn pointer `fn(&HasCtxt<'a>) -> &'a Ctxt`
-note: the lifetime `'a` as defined on the impl at 12:6...
- --> $DIR/regions-trait-1.rs:12:6
- |
-LL | impl<'a> GetCtxt for HasCtxt<'a> {
- | ^^
-note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 16:5
- --> $DIR/regions-trait-1.rs:16:5
- |
-LL | fn get_ctxt(&self) -> &'a Ctxt {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
#![allow(dead_code)]
trait Dummy<'a> {
- type Out;
+ type Out;
}
impl<'a, T> Dummy<'a> for T
-where T: 'a
+where
+ T: 'a,
{
- type Out = ();
+ type Out = ();
}
type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
enum Ref1<'a, T> {
- Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough
+ Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
}
enum Ref2<'a, T> {
Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
}
-enum RefOk<'a, T:'a> {
- RefOkVariant1(&'a T)
+enum RefOk<'a, T: 'a> {
+ RefOkVariant1(&'a T),
}
// This is now well formed. RFC 2093
enum RefIndirect<'a, T> {
- RefIndirectVariant1(isize, RefOk<'a,T>)
+ RefIndirectVariant1(isize, RefOk<'a, T>),
}
-enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309]
- RefDoubleVariant1(&'a RequireOutlives<'b, T>)
- //~^ the parameter type `T` may not live long enough [E0309]
+enum RefDouble<'a, 'b, T> {
+ RefDoubleVariant1(&'a RequireOutlives<'b, T>),
+ //~^ the parameter type `T` may not live long enough [E0309]
}
-fn main() { }
+fn main() {}
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:18:18
+ --> $DIR/regions-enum-not-wf.rs:19:18
|
LL | enum Ref1<'a, T> {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL | Ref1Variant1(RequireOutlives<'a, T>)
+LL | Ref1Variant1(RequireOutlives<'a, T>),
| ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:23:25
+ --> $DIR/regions-enum-not-wf.rs:24:25
|
LL | enum Ref2<'a, T> {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
| ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:35:1
- |
-LL | enum RefDouble<'a, 'b, T> {
- | ^ - help: consider adding an explicit lifetime bound...: `T: 'b`
- | _|
- | |
-LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-LL | |
-LL | | }
- | |_^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-enum-not-wf.rs:36:23
+ --> $DIR/regions-enum-not-wf.rs:37:23
|
LL | enum RefDouble<'a, 'b, T> {
| - help: consider adding an explicit lifetime bound...: `T: 'b`
-LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0309`.
--> $DIR/deafult-associated-type-bound-1.rs:18:5
|
LL | type U: Clone;
- | -------------- required by `X::U`
+ | ----- required by this bound in `X::U`
...
LL | default type U = str;
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
--> $DIR/deafult-associated-type-bound-2.rs:16:5
|
LL | type U: PartialEq<T>;
- | --------------------- required by `X::U`
+ | ------------ required by this bound in `X::U`
...
LL | default type U = &'static B;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B`
//~^^ WARNING the feature `generic_associated_types` is incomplete
trait X {
- type U<'a>: PartialEq<&'a Self>;
+ type U<'a>: PartialEq<&'a Self> where Self: 'a;
fn unsafe_compare<'b>(x: Option<Self::U<'b>>, y: Option<&'b Self>) {
match (x, y) {
(Some(a), Some(b)) => a == b,
error[E0277]: can't compare `T` with `T`
--> $DIR/deafult-generic-associated-type-bound.rs:19:5
|
-LL | type U<'a>: PartialEq<&'a Self>;
- | -------------------------------- required by `X::U`
+LL | type U<'a>: PartialEq<&'a Self> where Self: 'a;
+ | ------------------- required by this bound in `X::U`
...
LL | default type U<'a> = &'a T;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T == T`
--- /dev/null
+// build-fail
+//~^ ERROR overflow evaluating the requirement `i32: Check`
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Iterate<'a> {
+ type Ty: Valid;
+ fn iterate(self);
+}
+impl<'a, T> Iterate<'a> for T
+where
+ T: Check,
+{
+ default type Ty = ();
+ default fn iterate(self) {}
+}
+
+trait Check {}
+impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
+
+trait Valid {}
+
+impl Valid for () {}
+
+fn main() {
+ Iterate::iterate(0);
+}
--- /dev/null
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/issue-38091-2.rs:4:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error[E0275]: overflow evaluating the requirement `i32: Check`
+ |
+ = note: required because of the requirements on the impl of `Iterate` for `i32`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0275`.
--- /dev/null
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Iterate<'a> {
+ type Ty: Valid;
+ fn iterate(self);
+}
+impl<'a, T> Iterate<'a> for T
+where
+ T: Check,
+{
+ default type Ty = ();
+ //~^ ERROR the trait bound `(): Valid` is not satisfied
+ default fn iterate(self) {}
+}
+
+trait Check {}
+impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
+
+trait Valid {}
+
+fn main() {
+ Iterate::iterate(0);
+}
--- /dev/null
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/issue-38091.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error[E0277]: the trait bound `(): Valid` is not satisfied
+ --> $DIR/issue-38091.rs:12:5
+ |
+LL | type Ty: Valid;
+ | ----- required by this bound in `Iterate::Ty`
+...
+LL | default type Ty = ();
+ | ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
--> $DIR/issue-44861.rs:21:5
|
LL | type Data2: CoerceUnsized<*const [u8]>;
- | --------------------------------------- required by `Smartass::Data2`
+ | -------------------------- required by this bound in `Smartass::Data2`
...
LL | default type Data2 = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CoerceUnsized<*const [u8]>` is not implemented for `()`
--> $DIR/issue-59435.rs:11:5
|
LL | type MyType: Default;
- | --------------------- required by `MyTrait::MyType`
+ | ------- required by this bound in `MyTrait::MyType`
...
LL | default type MyType = MyStruct;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `MyStruct`
| ^^^^^^^^ the trait `Bar` is not implemented for `()`
LL | 5;
| - consider removing this semicolon
- |
- = note: the return type of a function must have a statically known size
error: aborting due to previous error
-// Running rustfix would cause the same suggestion to be applied multiple times, which results in
-// invalid code.
+// check-pass
trait Parent {
type Ty;
struct ParentWrapper<T>(T);
impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
- //~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
type Ty = A;
type Assoc = ChildWrapper<T::Assoc>;
- //~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
- //~| ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
}
fn main() {}
+++ /dev/null
-error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
- --> $DIR/missing-assoc-type-bound-restriction.rs:17:19
- |
-LL | trait Parent {
- | ------ required by a bound in this
-LL | type Ty;
-LL | type Assoc: Child<Self::Ty>;
- | --------------- required by this bound in `Parent`
-...
-LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
- | ^^^^^^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
- |
-help: consider further restricting the associated type
- |
-LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> where <T as Parent>::Assoc: Child<A> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
- --> $DIR/missing-assoc-type-bound-restriction.rs:20:18
- |
-LL | trait Parent {
- | ------ required by a bound in this
-LL | type Ty;
-LL | type Assoc: Child<Self::Ty>;
- | --------------- required by this bound in `Parent`
-...
-LL | type Assoc = ChildWrapper<T::Assoc>;
- | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
- |
- = note: required because of the requirements on the impl of `Child<A>` for `ChildWrapper<<T as Parent>::Assoc>`
-help: consider further restricting the associated type
- |
-LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> where <T as Parent>::Assoc: Child<A> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
- --> $DIR/missing-assoc-type-bound-restriction.rs:20:5
- |
-LL | trait Parent {
- | ------ required by a bound in this
-LL | type Ty;
-LL | type Assoc: Child<Self::Ty>;
- | --------------- required by this bound in `Parent`
-...
-LL | type Assoc = ChildWrapper<T::Assoc>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
- |
-help: consider further restricting the associated type
- |
-LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> where <T as Parent>::Assoc: Child<A> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
| help: consider removing the leading `&`-reference
|
= help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
+ = note: required because of the requirements on the impl of `IntoIterator` for `&Enumerate<std::slice::Iter<'_, {integer}>>`
= note: required by `into_iter`
error: aborting due to previous error
| help: consider removing 5 leading `&`-references
|
= help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
+ = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
= note: required by `into_iter`
error: aborting due to previous error
| |_____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
+ = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
= note: required by `into_iter`
error: aborting due to previous error
--- /dev/null
+// Check that we validate associated type bounds for trait objects
+
+trait X {
+ type Y: Clone;
+}
+
+fn f<T: X + ?Sized>() {
+ None::<T::Y>.clone();
+}
+
+fn main() {
+ f::<dyn X<Y = str>>();
+ //~^ ERROR the trait bound `str: Clone` is not satisfied
+}
--- /dev/null
+error[E0277]: the trait bound `str: Clone` is not satisfied
+ --> $DIR/check-trait-object-bounds-1.rs:12:5
+ |
+LL | fn f<T: X + ?Sized>() {
+ | - required by this bound in `f`
+...
+LL | f::<dyn X<Y = str>>();
+ | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Make sure that we're handling bound lifetimes correctly when validating trait
+// bounds.
+// run-pass
+
+trait X<'a> {
+ type F: FnOnce(&i32) -> &'a i32;
+}
+
+fn f<T: for<'r> X<'r> + ?Sized>() {
+ None::<T::F>.map(|f| f(&0));
+}
+
+fn main() {
+ f::<dyn for<'x> X<'x, F = fn(&i32) -> &'x i32>>();
+}
--- /dev/null
+// Check that we validate associated type bounds for trait objects when they
+// have bound lifetimes
+
+trait X<'a> {
+ type F: FnOnce(&i32) -> &'a i32;
+}
+
+fn f<T: for<'r> X<'r> + ?Sized>() {
+ None::<T::F>.map(|f| f(&0));
+}
+
+fn main() {
+ f::<dyn for<'x> X<'x, F = i32>>();
+ //~^ expected a `FnOnce<(&i32,)>` closure, found `i32`
+}
--- /dev/null
+error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32`
+ --> $DIR/check-trait-object-bounds-2.rs:13:5
+ |
+LL | fn f<T: for<'r> X<'r> + ?Sized>() {
+ | ------------- required by this bound in `f`
+...
+LL | f::<dyn for<'x> X<'x, F = i32>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32`
+ |
+ = help: the trait `for<'r> FnOnce<(&'r i32,)>` is not implemented for `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Check that we validate associated type bounds for trait objects
+
+trait X<'a> {
+ type Y: Into<&'static str> + From<&'a str>;
+}
+
+fn f<'a, T: X<'a> + ?Sized>(s: &'a str) -> &'static str {
+ T::Y::from(s).into()
+}
+
+pub fn main() {
+ let z;
+ {
+ let s = String::from("abcdef");
+ z = f::<dyn X<Y = &str>>(&s);
+ //~^ ERROR `s` does not live long enough
+ }
+
+ println!("{}", z)
+}
--- /dev/null
+error[E0597]: `s` does not live long enough
+ --> $DIR/check-trait-object-bounds-3.rs:15:34
+ |
+LL | z = f::<dyn X<Y = &str>>(&s);
+ | ---------------------^^-
+ | | |
+ | | borrowed value does not live long enough
+ | argument requires that `s` is borrowed for `'static`
+LL |
+LL | }
+ | - `s` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
--- /dev/null
+// Check that we validate associated type bounds on super traits for trait
+// objects
+
+trait Super {
+ type Y: Clone;
+}
+
+trait X: Super {}
+
+fn f<T: X + ?Sized>() {
+ None::<T::Y>.clone();
+}
+
+fn main() {
+ f::<dyn X<Y = str>>();
+ //~^ ERROR the trait bound `str: Clone` is not satisfied
+}
--- /dev/null
+error[E0277]: the trait bound `str: Clone` is not satisfied
+ --> $DIR/check-trait-object-bounds-4.rs:15:5
+ |
+LL | fn f<T: X + ?Sized>() {
+ | - required by this bound in `f`
+...
+LL | f::<dyn X<Y = str>>();
+ | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Check that we validate associated type bounds on super traits for trait
+// objects
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Super {
+ type V;
+}
+
+trait Obj: Super {
+ type U: Is<T = Self::V>;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i64>) {
+ is_obj(x)
+ //~^ type mismatch resolving `<i32 as Is>::T == i64`
+}
+
+fn main() {}
--- /dev/null
+error[E0271]: type mismatch resolving `<i32 as Is>::T == i64`
+ --> $DIR/check-trait-object-bounds-5.rs:23:5
+ |
+LL | fn is_obj<T: ?Sized + Obj>(_: &T) {}
+ | --- required by this bound in `is_obj`
+...
+LL | is_obj(x)
+ | ^^^^^^ expected `i64`, found `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
--- /dev/null
+// Check that we validate associated type bounds on super traits for trait
+// objects
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Obj {
+ type U: Is<T = Self::V>;
+ type V;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i64>) {
+ is_obj(x)
+ //~^ ERROR type mismatch resolving `<i32 as Is>::T == i64`
+}
+
+fn main() {}
--- /dev/null
+error[E0271]: type mismatch resolving `<i32 as Is>::T == i64`
+ --> $DIR/check-trait-object-bounds-6.rs:20:5
+ |
+LL | fn is_obj<T: ?Sized + Obj>(_: &T) {}
+ | --- required by this bound in `is_obj`
+...
+LL | is_obj(x)
+ | ^^^^^^ expected `i64`, found `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
_storage: Box<DB::Storage>,
}
struct SalsaStorage {
- _parse: <ParseQuery as Query<RootDatabase>>::Data, //~ ERROR overflow
+ _parse: <ParseQuery as Query<RootDatabase>>::Data,
}
impl Database for RootDatabase {
- type Storage = SalsaStorage; //~ ERROR overflow
+ // This would also be an error if we didn't abort compilation on the error
+ // above.
+ type Storage = SalsaStorage;
}
impl HasQueryGroup for RootDatabase {}
impl<DB> Query<DB> for ParseQuery
// we used to fail to report an error here because we got the
// caching wrong.
SourceDatabase::parse(db);
+ //~^ ERROR overflow
22
}
-error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase`
- --> $DIR/cycle-cache-err-60010.rs:27:13
+error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
+ --> $DIR/cycle-cache-err-60010.rs:69:5
|
-LL | _parse: <ParseQuery as Query<RootDatabase>>::Data,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
-
-error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe`
- --> $DIR/cycle-cache-err-60010.rs:31:20
- |
-LL | trait Database {
- | -------- required by a bound in this
-LL | type Storage;
- | ------------- required by this bound in `Database`
+LL | fn parse(&self) {
+ | --------------- required by `SourceDatabase::parse`
...
-LL | type Storage = SalsaStorage;
- | ^^^^^^^^^^^^
+LL | SourceDatabase::parse(db);
+ | ^^^^^^^^^^^^^^^^^^^^^
|
+ = note: required because it appears within the type `*const SalsaStorage`
+ = note: required because it appears within the type `Unique<SalsaStorage>`
+ = note: required because it appears within the type `Box<SalsaStorage>`
+ = note: required because it appears within the type `Runtime<RootDatabase>`
= note: required because it appears within the type `RootDatabase`
= note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase`
- = note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
- = note: required because it appears within the type `SalsaStorage`
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0275`.
--- /dev/null
+// Check that we don't have a cycle when we try to normalize `Self::U` in the
+// bound below.
+
+// check-pass
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Obj {
+ type U: Is<T = Self::U>;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32>) {
+ is_obj(x)
+}
+
+fn main() {}
--- /dev/null
+// Check that we don't have a cycle when we try to normalize `Self::V` in the
+// bound below.
+
+// check-pass
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Super {
+ type V;
+}
+
+trait Obj: Super {
+ type U: Is<T = Self::V>;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i32>) {
+ is_obj(x)
+}
+
+fn main() {}
--- /dev/null
+// Check that we don't have a cycle when we try to normalize `Self::V` in the
+// bound below.
+
+// check-pass
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Obj {
+ type U: Is<T = Self::V>;
+ type V;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i32>) {
+ is_obj(x)
+}
+
+fn main() {}
--- /dev/null
+// Check that we don't have a cycle when we try to normalize `Self::U` in the
+// bound below. Make sure that having a lifetime on the trait object doesn't break things
+
+// check-pass
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Obj<'a> {
+ type U: Is<T = Self::V>;
+ type V;
+}
+
+fn is_obj<'a, T: ?Sized + Obj<'a>>(_: &T) {}
+
+fn f<'a>(x: &dyn Obj<'a, U = i32, V = i32>) {
+ is_obj(x)
+}
+
+fn main() {}
--- /dev/null
+// check-pass
+
+use std::any::Any;
+
+trait A<T>: Any {
+ fn m(&self) {}
+}
+
+impl<S, T: 'static> A<S> for T {}
+
+fn call_obj<'a>() {
+ let obj: &dyn A<&'a ()> = &();
+ obj.m();
+}
+
+fn main() {}
}
impl<T: Magic> Magic for T {
type X = Self;
+ //~^ ERROR E0277
}
fn check<T: Trait>() {}
+error[E0277]: `T` cannot be shared between threads safely
+ --> $DIR/traits-inductive-overflow-two-traits.rs:11:5
+ |
+LL | type X: Trait;
+ | ----- required by this bound in `Magic::X`
+...
+LL | type X = Self;
+ | ^^^^^^^^^^^^^^ `T` cannot be shared between threads safely
+ |
+help: consider further restricting this bound
+ |
+LL | impl<T: Magic + Sync> Magic for T {
+ | ^^^^^^
+
error[E0275]: overflow evaluating the requirement `*mut (): Magic`
- --> $DIR/traits-inductive-overflow-two-traits.rs:19:5
+ --> $DIR/traits-inductive-overflow-two-traits.rs:20:5
|
LL | fn wizard<T: Magic>() { check::<<T as Magic>::X>(); }
| ----- required by this bound in `wizard`
LL | wizard::<*mut ()>();
| ^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0275`.
+Some errors have detailed explanations: E0275, E0277.
+For more information about an error, try `rustc --explain E0275`.
let res: Result<i32, i32> = try { }; //~ ERROR type mismatch
- let res: () = try { }; //~ the trait bound `(): Try` is not satisfied
+ let res: () = try { };
+ //~^ ERROR the trait bound `(): Try` is not satisfied
+ //~| ERROR the trait bound `(): Try` is not satisfied
let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied
}
| ^ expected `i32`, found `()`
error[E0277]: the trait bound `(): Try` is not satisfied
- --> $DIR/try-block-bad-type.rs:17:23
+ --> $DIR/try-block-bad-type.rs:17:25
|
LL | let res: () = try { };
- | ^^^ the trait `Try` is not implemented for `()`
+ | ^ the trait `Try` is not implemented for `()`
|
= note: required by `from_ok`
+error[E0277]: the trait bound `(): Try` is not satisfied
+ --> $DIR/try-block-bad-type.rs:17:25
+ |
+LL | let res: () = try { };
+ | ^ the trait `Try` is not implemented for `()`
+
error[E0277]: the trait bound `i32: Try` is not satisfied
- --> $DIR/try-block-bad-type.rs:19:24
+ --> $DIR/try-block-bad-type.rs:21:26
|
LL | let res: i32 = try { 5 };
- | ^^^^^ the trait `Try` is not implemented for `i32`
+ | ^ the trait `Try` is not implemented for `i32`
|
= note: required by `from_ok`
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
error[E0277]: the trait bound `bool: Try` is not satisfied
- --> $DIR/try-block-in-while.rs:6:15
+ --> $DIR/try-block-in-while.rs:6:17
|
LL | while try { false } {}
- | ^^^^^^^^^ the trait `Try` is not implemented for `bool`
+ | ^^^^^ the trait `Try` is not implemented for `bool`
|
= note: required by `from_ok`
--- /dev/null
+// Make sure that we check that impl trait types implement the traits that they
+// claim to.
+
+#![feature(type_alias_impl_trait)]
+
+type X<T> = impl Clone;
+//~^ ERROR the trait bound `T: Clone` is not satisfied
+
+fn f<T: Clone>(t: T) -> X<T> {
+ t
+}
+
+fn g<T>(o: Option<X<T>>) -> Option<X<T>> {
+ o.clone()
+}
+
+fn main() {
+ g(None::<X<&mut ()>>);
+}
--- /dev/null
+error[E0277]: the trait bound `T: Clone` is not satisfied
+ --> $DIR/bounds-are-checked-2.rs:6:13
+ |
+LL | type X<T> = impl Clone;
+ | ^^^^^^^^^^ the trait `Clone` is not implemented for `T`
+ |
+help: consider restricting type parameter `T`
+ |
+LL | type X<T: Clone> = impl Clone;
+ | ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Make sure that we check that impl trait types implement the traits that they
+// claim to.
+
+#![feature(type_alias_impl_trait)]
+
+type X<'a> = impl Into<&'static str> + From<&'a str>;
+//~^ ERROR mismatched types
+
+fn f<'a: 'static>(t: &'a str) -> X<'a> {
+ //~^ WARNING unnecessary lifetime parameter
+ t
+}
+
+fn extend_lt<'a>(o: &'a str) -> &'static str {
+ X::<'_>::from(o).into()
+}
+
+fn main() {
+ let r =
+ {
+ let s = "abcdef".to_string();
+ extend_lt(&s)
+ };
+ println!("{}", r);
+}
--- /dev/null
+warning: unnecessary lifetime parameter `'a`
+ --> $DIR/bounds-are-checked.rs:9:6
+ |
+LL | fn f<'a: 'static>(t: &'a str) -> X<'a> {
+ | ^^^^^^^^^^^
+ |
+ = help: you can use the `'static` lifetime directly, in place of `'a`
+
+error[E0308]: mismatched types
+ --> $DIR/bounds-are-checked.rs:6:14
+ |
+LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+ |
+ = note: expected trait `From<&'a str>`
+ found trait `From<&'static str>`
+note: the lifetime `'a` as defined on the item at 6:8...
+ --> $DIR/bounds-are-checked.rs:6:8
+ |
+LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
+ | ^^
+ = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
#![feature(type_alias_impl_trait)]
use std::fmt::Debug;
fn main() {}
-type Two<T, U> = impl Debug;
+type Two<T: Debug, U> = impl Debug;
fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
(t, 4u32)
// test that unused generic parameters are ok
type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
+//~| ERROR `U` doesn't implement `Debug`
fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(t, u)
}
fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-//~^ concrete type differs from previous
+ //~^ concrete type differs from previous
(u, t)
}
error: concrete type differs from previous defining opaque type use
- --> $DIR/generic_duplicate_param_use5.rs:14:1
+ --> $DIR/generic_duplicate_param_use5.rs:16:1
|
LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, U)`, got `(U, T)`
|
note: previous use here
- --> $DIR/generic_duplicate_param_use5.rs:10:1
+ --> $DIR/generic_duplicate_param_use5.rs:12:1
|
LL | fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error[E0277]: `T` doesn't implement `Debug`
+ --> $DIR/generic_duplicate_param_use5.rs:8:18
+ |
+LL | type Two<T, U> = impl Debug;
+ | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: required because of the requirements on the impl of `Debug` for `(T, U)`
+help: consider restricting type parameter `T`
+ |
+LL | type Two<T: Debug, U> = impl Debug;
+ | ^^^^^^^
+
+error[E0277]: `U` doesn't implement `Debug`
+ --> $DIR/generic_duplicate_param_use5.rs:8:18
+ |
+LL | type Two<T, U> = impl Debug;
+ | ^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: required because of the requirements on the impl of `Debug` for `(T, U)`
+help: consider restricting type parameter `U`
+ |
+LL | type Two<T, U: Debug> = impl Debug;
+ | ^^^^^^^
+
+error: aborting due to 3 previous errors
+For more information about this error, try `rustc --explain E0277`.
// test that unused generic parameters are ok
type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(t, t)
}
fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
- //~^ concrete type differs from previous
+ //~^ ERROR concrete type differs from previous
(u, t)
}
error: concrete type differs from previous defining opaque type use
- --> $DIR/generic_duplicate_param_use6.rs:14:1
+ --> $DIR/generic_duplicate_param_use6.rs:15:1
|
LL | fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, T)`, got `(U, T)`
|
note: previous use here
- --> $DIR/generic_duplicate_param_use6.rs:10:1
+ --> $DIR/generic_duplicate_param_use6.rs:11:1
|
LL | fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error[E0277]: `T` doesn't implement `Debug`
+ --> $DIR/generic_duplicate_param_use6.rs:8:18
+ |
+LL | type Two<T, U> = impl Debug;
+ | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: required because of the requirements on the impl of `Debug` for `(T, T)`
+help: consider restricting type parameter `T`
+ |
+LL | type Two<T: Debug, U> = impl Debug;
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0277`.
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
#![feature(type_alias_impl_trait)]
use std::fmt::Debug;
fn main() {}
-type Two<A, B> = impl Debug;
+type Two<A: Debug, B> = impl Debug;
fn two<T: Debug + Copy, U>(t: T, u: U) -> Two<T, U> {
(t, t)
fn main() {}
type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
(t, 4u32)
}
fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
-//~^ concrete type differs from previous
+ //~^ concrete type differs from previous
(u, 4u32)
}
error: concrete type differs from previous defining opaque type use
- --> $DIR/generic_duplicate_param_use8.rs:13:1
+ --> $DIR/generic_duplicate_param_use8.rs:14:1
|
LL | fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
|
note: previous use here
- --> $DIR/generic_duplicate_param_use8.rs:9:1
+ --> $DIR/generic_duplicate_param_use8.rs:10:1
|
LL | fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error[E0277]: `T` doesn't implement `Debug`
+ --> $DIR/generic_duplicate_param_use8.rs:7:18
+ |
+LL | type Two<T, U> = impl Debug;
+ | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: required because of the requirements on the impl of `Debug` for `(T, u32)`
+help: consider restricting type parameter `T`
+ |
+LL | type Two<T: Debug, U> = impl Debug;
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0277`.
fn main() {}
type Two<A, B> = impl Debug;
+//~^ ERROR the trait bound `A: Foo` is not satisfied in `(A, B, <A as Foo>::Bar)`
+//~| ERROR `A` doesn't implement `Debug`
+//~| ERROR `B` doesn't implement `Debug`
trait Foo {
type Bar: Debug;
error: concrete type differs from previous defining opaque type use
- --> $DIR/generic_duplicate_param_use9.rs:18:1
+ --> $DIR/generic_duplicate_param_use9.rs:21:1
|
LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
|
note: previous use here
- --> $DIR/generic_duplicate_param_use9.rs:14:1
+ --> $DIR/generic_duplicate_param_use9.rs:17:1
|
LL | fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error[E0277]: the trait bound `A: Foo` is not satisfied in `(A, B, <A as Foo>::Bar)`
+ --> $DIR/generic_duplicate_param_use9.rs:7:18
+ |
+LL | type Two<A, B> = impl Debug;
+ | ^^^^^^^^^^ within `(A, B, <A as Foo>::Bar)`, the trait `Foo` is not implemented for `A`
+ |
+ = note: required because it appears within the type `(A, B, <A as Foo>::Bar)`
+help: consider restricting type parameter `A`
+ |
+LL | type Two<A: Foo, B> = impl Debug;
+ | ^^^^^
+
+error[E0277]: `A` doesn't implement `Debug`
+ --> $DIR/generic_duplicate_param_use9.rs:7:18
+ |
+LL | type Two<A, B> = impl Debug;
+ | ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)`
+help: consider restricting type parameter `A`
+ |
+LL | type Two<A: Debug, B> = impl Debug;
+ | ^^^^^^^
+
+error[E0277]: `B` doesn't implement `Debug`
+ --> $DIR/generic_duplicate_param_use9.rs:7:18
+ |
+LL | type Two<A, B> = impl Debug;
+ | ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)`
+help: consider restricting type parameter `B`
+ |
+LL | type Two<A, B: Debug> = impl Debug;
+ | ^^^^^^^
+
+error: aborting due to 4 previous errors
+For more information about this error, try `rustc --explain E0277`.
= note: expected type `i32`
found opaque type `impl Sized`
-error: aborting due to 2 previous errors
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/generic_type_does_not_live_long_enough.rs:14:30
+ |
+LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
+ | ^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `T: 'static`...
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+ |
+LL | type WrongGeneric<T> = impl 'static;
+ | ^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `T: 'static`...
+ = note: ...so that the type `T` will meet its required lifetime bounds
+
+error: aborting due to 4 previous errors
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0308, E0310.
+For more information about an error, try `rustc --explain E0308`.
type WrongGeneric<T> = impl 'static;
//~^ ERROR the parameter type `T` may not live long enough
-//~^^ ERROR: at least one trait must be specified
+//~| ERROR the parameter type `T` may not live long enough
+//~| ERROR: at least one trait must be specified
fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
t
LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
-error: aborting due to 3 previous errors
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+ |
+LL | type WrongGeneric<T> = impl 'static;
+ | ^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `T: 'static`...
+ = note: ...so that the type `T` will meet its required lifetime bounds
+
+error: aborting due to 4 previous errors
Some errors have detailed explanations: E0308, E0310.
For more information about an error, try `rustc --explain E0308`.
error: higher-ranked subtype error
- --> $DIR/issue-57611-trait-alias.rs:21:9
+ --> $DIR/issue-57611-trait-alias.rs:25:9
|
LL | |x| x
| ^^^^^
error: higher-ranked subtype error
- --> $DIR/issue-57611-trait-alias.rs:21:9
+ --> $DIR/issue-57611-trait-alias.rs:25:9
|
LL | |x| x
| ^^^^^
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+ --> $DIR/issue-57611-trait-alias.rs:17:16
+ |
+LL | type Bar = impl Baz<Self, Self>;
+ | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `for<'r> Fn<(&'r X,)>`
+ found type `Fn<(&'static X,)>`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-57611-trait-alias.rs:17:16
+ |
+LL | type Bar = impl Baz<Self, Self>;
+ | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `FnOnce<(&X,)>`
+ found type `FnOnce<(&'static X,)>`
+
+error: aborting due to 4 previous errors
+For more information about this error, try `rustc --explain E0308`.
impl Foo for X {
type Bar = impl Baz<Self, Self>;
//~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
fn bar(&self) -> Self::Bar {
|x| x
= note: expected type `FnOnce<(&X,)>`
found type `FnOnce<(&X,)>`
-error: aborting due to previous error
+error[E0308]: mismatched types
+ --> $DIR/issue-57611-trait-alias.rs:17:16
+ |
+LL | type Bar = impl Baz<Self, Self>;
+ | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `for<'r> Fn<(&'r X,)>`
+ found type `Fn<(&'<empty> X,)>`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-57611-trait-alias.rs:17:16
+ |
+LL | type Bar = impl Baz<Self, Self>;
+ | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `FnOnce<(&X,)>`
+ found type `FnOnce<(&'<empty> X,)>`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-57611-trait-alias.rs:17:16
+ |
+LL | type Bar = impl Baz<Self, Self>;
+ | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `for<'r> Fn<(&'r X,)>`
+ found type `Fn<(&'<empty> X,)>`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-57611-trait-alias.rs:17:16
+ |
+LL | type Bar = impl Baz<Self, Self>;
+ | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `FnOnce<(&X,)>`
+ found type `FnOnce<(&'<empty> X,)>`
+
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.
|
= help: the following implementations were found:
<&() as Bug>
- = note: the return type of a function must have a statically known size
error: could not find defining uses
--> $DIR/issue-60371.rs:8:17
|
= note: expected opaque type `impl FnOnce<()>`
found unit type `()`
- = note: the return type of a function must have a statically known size
error: aborting due to previous error
}
trait Trait {}
-type GenericBound<'a, T: Trait> = impl Sized + 'a;
+type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a;
fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> {
t
}
mod pass_through {
- pub type Passthrough<T> = impl Sized + 'static;
+ pub type Passthrough<T: 'static> = impl Sized + 'static;
fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
t
| ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32`
|
= help: the trait `Add<u32>` is not implemented for `i32`
+ = note: required by `add`
error[E0308]: mismatched types
--> $DIR/ufcs-qpath-self-mismatch.rs:6:28
use rustc_hir::{Body, FnDecl, HirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{Opaque, PredicateAtom::Trait};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span};
}
let ret_ty = utils::return_ty(cx, hir_id);
if let Opaque(id, subst) = *ret_ty.kind() {
- let preds = cx.tcx.predicates_of(id).instantiate(cx.tcx, subst);
+ let preds = cx.tcx.explicit_item_bounds(id);
let mut is_future = false;
- for p in preds.predicates {
+ for &(p, _span) in preds {
+ let p = p.subst(cx.tcx, subst);
if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() {
is_future = true;
|db| {
cx.tcx.infer_ctxt().enter(|infcx| {
for FulfillmentError { obligation, .. } in send_errors {
- infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
- if let Trait(trait_pred, _) = obligation.predicate.skip_binders() {
+ infcx.maybe_note_obligation_cause_for_async_await(
+ db,
+ &obligation,
+ );
+ if let Trait(trait_pred, _) =
+ obligation.predicate.skip_binders()
+ {
db.note(&format!(
"`{}` doesn't implement `{}`",
trait_pred.self_ty(),
// if return type is impl trait, check the associated types
if let ty::Opaque(def_id, _) = *ret_ty.kind() {
// one of the associated types must be Self
- for &(predicate, _span) in cx.tcx.predicates_of(def_id).predicates {
- if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() {
+ for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
+ if let ty::PredicateAtom::Projection(projection_predicate) =
+ predicate.skip_binders()
+ {
// walk the associated type and check for Self
if contains_ty(projection_predicate.ty, self_ty) {
return;
},
ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
ty::Opaque(ref def_id, _) => {
- for (predicate, _) in cx.tcx.predicates_of(*def_id).predicates {
+ for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
if let ty::PredicateAtom::Trait(trait_predicate, _) = predicate.skip_binders() {
- if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
+ if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some()
+ {
return true;
}
}