Auto merge of #120862 - matthiaskrgr:rollup-jzfab58, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #120584 (For a rigid projection, recursively look at the self type's item bounds to fix the `associated_type_bounds` feature)
 - #120596 ([rustdoc] Correctly generate path for non-local items in source code pages)
 - #120629 (Move some test files)
 - #120846 (Update jobserver-rs to 0.1.28)
 - #120850 (ast_lowering: Fix regression in `use ::{}` imports.)
 - #120853 (Avoid a collection and iteration on empty passes)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-02-10 00:03:43 +00:00
commit b5c46dc542
68 changed files with 576 additions and 535 deletions

View File

@ -2090,9 +2090,9 @@ dependencies = [
[[package]] [[package]]
name = "jobserver" name = "jobserver"
version = "0.1.27" version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
dependencies = [ dependencies = [
"libc", "libc",
] ]

View File

@ -569,7 +569,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
}); });
} }
let path = if trees.is_empty() && !prefix.segments.is_empty() { // Condition should match `build_reduced_graph_for_use_tree`.
let path = if trees.is_empty()
&& !(prefix.segments.is_empty()
|| prefix.segments.len() == 1
&& prefix.segments[0].ident.name == kw::PathRoot)
{
// For empty lists we need to lower the prefix so it is checked for things // For empty lists we need to lower the prefix so it is checked for things
// like stability later. // like stability later.
let res = self.lower_import_res(id, span); let res = self.lower_import_res(id, span);

View File

@ -1092,24 +1092,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Piggy-back on the `impl Trait` context to figure out the correct behavior. // Piggy-back on the `impl Trait` context to figure out the correct behavior.
let desugar_kind = match itctx { let desugar_kind = match itctx {
// We are in the return position: // in an argument, RPIT, or TAIT, if we are within a dyn type:
//
// fn foo() -> impl Iterator<Item: Debug>
//
// so desugar to
//
// fn foo() -> impl Iterator<Item = impl Debug>
ImplTraitContext::ReturnPositionOpaqueTy { .. }
| ImplTraitContext::TypeAliasesOpaqueTy { .. } => DesugarKind::ImplTrait,
// We are in the argument position, but within a dyn type:
// //
// fn foo(x: dyn Iterator<Item: Debug>) // fn foo(x: dyn Iterator<Item: Debug>)
// //
// so desugar to // then desugar to:
// //
// fn foo(x: dyn Iterator<Item = impl Debug>) // fn foo(x: dyn Iterator<Item = impl Debug>)
ImplTraitContext::Universal if self.is_in_dyn_type => DesugarKind::ImplTrait, //
// This is because dyn traits must have all of their associated types specified.
ImplTraitContext::ReturnPositionOpaqueTy { .. }
| ImplTraitContext::TypeAliasesOpaqueTy { .. }
| ImplTraitContext::Universal
if self.is_in_dyn_type =>
{
DesugarKind::ImplTrait
}
ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => { ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => {
DesugarKind::Error(position) DesugarKind::Error(position)

View File

@ -9,7 +9,7 @@ ar_archive_writer = "0.1.5"
bitflags = "2.4.1" bitflags = "2.4.1"
cc = "1.0.69" cc = "1.0.69"
itertools = "0.11" itertools = "0.11"
jobserver = "0.1.27" jobserver = "0.1.28"
pathdiff = "0.2.0" pathdiff = "0.2.0"
regex = "1.4" regex = "1.4"
rustc_arena = { path = "../rustc_arena" } rustc_arena = { path = "../rustc_arena" }

View File

@ -11,7 +11,7 @@ either = "1.0"
elsa = "=1.7.1" elsa = "=1.7.1"
ena = "0.14.2" ena = "0.14.2"
indexmap = { version = "2.0.0" } indexmap = { version = "2.0.0" }
jobserver_crate = { version = "0.1.27", package = "jobserver" } jobserver_crate = { version = "0.1.28", package = "jobserver" }
libc = "0.2" libc = "0.2"
measureme = "11" measureme = "11"
rustc-hash = "1.1.0" rustc-hash = "1.1.0"

View File

@ -23,7 +23,10 @@ static GLOBAL_CLIENT: LazyLock<Result<Client, String>> = LazyLock::new(|| {
if matches!( if matches!(
error.kind(), error.kind(),
FromEnvErrorKind::NoEnvVar | FromEnvErrorKind::NoJobserver | FromEnvErrorKind::Unsupported FromEnvErrorKind::NoEnvVar
| FromEnvErrorKind::NoJobserver
| FromEnvErrorKind::NegativeFd
| FromEnvErrorKind::Unsupported
) { ) {
return Ok(default_client()); return Ok(default_client());
} }

View File

@ -364,14 +364,11 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
// Note: `passes` is often empty. In that case, it's faster to run // Note: `passes` is often empty. In that case, it's faster to run
// `builtin_lints` directly rather than bundling it up into the // `builtin_lints` directly rather than bundling it up into the
// `RuntimeCombinedLateLintPass`. // `RuntimeCombinedLateLintPass`.
let mut passes: Vec<_> = unerased_lint_store(tcx.sess) let late_module_passes = &unerased_lint_store(tcx.sess).late_module_passes;
.late_module_passes if late_module_passes.is_empty() {
.iter()
.map(|mk_pass| (mk_pass)(tcx))
.collect();
if passes.is_empty() {
late_lint_mod_inner(tcx, module_def_id, context, builtin_lints); late_lint_mod_inner(tcx, module_def_id, context, builtin_lints);
} else { } else {
let mut passes: Vec<_> = late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
passes.push(Box::new(builtin_lints)); passes.push(Box::new(builtin_lints));
let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] }; let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
late_lint_mod_inner(tcx, module_def_id, context, pass); late_lint_mod_inner(tcx, module_def_id, context, pass);

View File

@ -548,7 +548,27 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
goal: Goal<'tcx, G>, goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>, candidates: &mut Vec<Candidate<'tcx>>,
) { ) {
let alias_ty = match goal.predicate.self_ty().kind() { let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
ecx.assemble_alias_bound_candidates_recur(goal.predicate.self_ty(), goal, candidates);
});
}
/// For some deeply nested `<T>::A::B::C::D` rigid associated type,
/// we should explore the item bounds for all levels, since the
/// `associated_type_bounds` feature means that a parent associated
/// type may carry bounds for a nested associated type.
///
/// If we have a projection, check that its self type is a rigid projection.
/// If so, continue searching by recursively calling after normalization.
// FIXME: This may recurse infinitely, but I can't seem to trigger it without
// hitting another overflow error something. Add a depth parameter needed later.
fn assemble_alias_bound_candidates_recur<G: GoalKind<'tcx>>(
&mut self,
self_ty: Ty<'tcx>,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
) {
let (kind, alias_ty) = match *self_ty.kind() {
ty::Bool ty::Bool
| ty::Char | ty::Char
| ty::Int(_) | ty::Int(_)
@ -573,13 +593,27 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::Param(_) | ty::Param(_)
| ty::Placeholder(..) | ty::Placeholder(..)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Alias(ty::Inherent, _)
| ty::Alias(ty::Weak, _)
| ty::Error(_) => return, | ty::Error(_) => return,
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => {
| ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"), bug!("unexpected self type for `{goal:?}`")
// Excluding IATs and type aliases here as they don't have meaningful item bounds. }
ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty,
ty::Infer(ty::TyVar(_)) => {
// If we hit infer when normalizing the self type of an alias,
// then bail with ambiguity. We should never encounter this on
// the *first* iteration of this recursive function.
if let Ok(result) =
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
{
candidates.push(Candidate { source: CandidateSource::AliasBound, result });
}
return;
}
ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty),
ty::Alias(ty::Inherent | ty::Weak, _) => {
unreachable!("Weak and Inherent aliases should have been normalized away already")
}
}; };
for assumption in for assumption in
@ -587,9 +621,28 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
{ {
match G::consider_alias_bound_candidate(self, goal, assumption) { match G::consider_alias_bound_candidate(self, goal, assumption) {
Ok(result) => { Ok(result) => {
candidates.push(Candidate { source: CandidateSource::AliasBound, result }) candidates.push(Candidate { source: CandidateSource::AliasBound, result });
}
Err(NoSolution) => {}
}
}
if kind != ty::Projection {
return;
}
match self.try_normalize_ty(goal.param_env, alias_ty.self_ty()) {
// Recurse on the self type of the projection.
Some(next_self_ty) => {
self.assemble_alias_bound_candidates_recur(next_self_ty, goal, candidates);
}
// Bail if we overflow when normalizing, adding an ambiguous candidate.
None => {
if let Ok(result) =
self.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW)
{
candidates.push(Candidate { source: CandidateSource::AliasBound, result });
} }
Err(NoSolution) => (),
} }
} }
} }

View File

@ -40,6 +40,7 @@ use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::ops::ControlFlow;
pub use rustc_middle::traits::Reveal; pub use rustc_middle::traits::Reveal;
@ -1614,32 +1615,44 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
candidate_set: &mut ProjectionCandidateSet<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>,
) { ) {
debug!("assemble_candidates_from_trait_def(..)"); debug!("assemble_candidates_from_trait_def(..)");
let mut ambiguous = false;
selcx.for_each_item_bound(
obligation.predicate.self_ty(),
|selcx, clause, _| {
let Some(clause) = clause.as_projection_clause() else {
return ControlFlow::Continue(());
};
let tcx = selcx.tcx(); let is_match =
// Check whether the self-type is itself a projection. selcx.infcx.probe(|_| selcx.match_projection_projections(obligation, clause, true));
// If so, extract what we know from the trait and try to come up with a good answer.
let bounds = match *obligation.predicate.self_ty().kind() {
// Excluding IATs and type aliases here as they don't have meaningful item bounds.
ty::Alias(ty::Projection | ty::Opaque, ref data) => {
tcx.item_bounds(data.def_id).instantiate(tcx, data.args)
}
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.mark_ambiguous();
return;
}
_ => return,
};
assemble_candidates_from_predicates( match is_match {
selcx, ProjectionMatchesProjection::Yes => {
obligation, candidate_set.push_candidate(ProjectionCandidate::TraitDef(clause));
candidate_set,
ProjectionCandidate::TraitDef, if !obligation.predicate.has_non_region_infer() {
bounds.iter(), // HACK: Pick the first trait def candidate for a fully
true, // inferred predicate. This is to allow duplicates that
// differ only in normalization.
return ControlFlow::Break(());
}
}
ProjectionMatchesProjection::Ambiguous => {
candidate_set.mark_ambiguous();
}
ProjectionMatchesProjection::No => {}
}
ControlFlow::Continue(())
},
// `ProjectionCandidateSet` is borrowed in the above closure,
// so just mark ambiguous outside of the closure.
|| ambiguous = true,
); );
if ambiguous {
candidate_set.mark_ambiguous();
}
} }
/// In the case of a trait object like /// In the case of a trait object like

View File

@ -6,13 +6,16 @@
//! //!
//! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
use std::ops::ControlFlow;
use hir::def_id::DefId; use hir::def_id::DefId;
use hir::LangItem; use hir::LangItem;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError}; use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt};
use crate::traits; use crate::traits;
use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::query::evaluate_obligation::InferCtxtExt;
@ -158,11 +161,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => return, _ => return,
} }
let result = self self.infcx.probe(|_| {
.infcx let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); let placeholder_trait_predicate =
self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);
debug!(?placeholder_trait_predicate);
candidates.vec.extend(result.into_iter().map(|idx| ProjectionCandidate(idx))); // 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();
self.for_each_item_bound::<!>(
placeholder_trait_predicate.self_ty(),
|selcx, bound, idx| {
let Some(bound) = bound.as_trait_clause() else {
return ControlFlow::Continue(());
};
if bound.polarity() != placeholder_trait_predicate.polarity {
return ControlFlow::Continue(());
}
selcx.infcx.probe(|_| {
match selcx.match_normalize_trait_ref(
obligation,
bound.to_poly_trait_ref(),
placeholder_trait_predicate.trait_ref,
) {
Ok(None) => {
candidates.vec.push(ProjectionCandidate(idx));
}
Ok(Some(normalized_trait))
if distinct_normalized_bounds.insert(normalized_trait) =>
{
candidates.vec.push(ProjectionCandidate(idx));
}
_ => {}
}
});
ControlFlow::Continue(())
},
// On ambiguity.
|| candidates.ambiguous = true,
);
});
} }
/// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller /// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller

View File

@ -162,20 +162,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref; self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref;
let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_self_ty = placeholder_trait_predicate.self_ty();
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
let (def_id, args) = match *placeholder_self_ty.kind() {
// Excluding IATs and type aliases here as they don't have meaningful item bounds.
ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
(def_id, args)
}
_ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
};
let candidate_predicate = let candidate_predicate = self
tcx.item_bounds(def_id).map_bound(|i| i[idx]).instantiate(tcx, args); .for_each_item_bound(
placeholder_self_ty,
|_, clause, clause_idx| {
if clause_idx == idx {
ControlFlow::Break(clause)
} else {
ControlFlow::Continue(())
}
},
|| unreachable!(),
)
.break_value()
.expect("expected to index into clause that exists");
let candidate = candidate_predicate let candidate = candidate_predicate
.as_trait_clause() .as_trait_clause()
.expect("projection candidate is not a trait predicate") .expect("projection candidate is not a trait predicate")
.map_bound(|t| t.trait_ref); .map_bound(|t| t.trait_ref);
let mut obligations = Vec::new(); let mut obligations = Vec::new();
let candidate = normalize_with_depth_to( let candidate = normalize_with_depth_to(
self, self,
@ -194,8 +200,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map_err(|_| Unimplemented) .map_err(|_| Unimplemented)
})?); })?);
if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() { // FIXME(compiler-errors): I don't think this is needed.
let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args); if let ty::Alias(ty::Projection, alias_ty) = placeholder_self_ty.kind() {
let predicates = tcx.predicates_of(alias_ty.def_id).instantiate_own(tcx, alias_ty.args);
for (predicate, _) in predicates { for (predicate, _) in predicates {
let normalized = normalize_with_depth_to( let normalized = normalize_with_depth_to(
self, self,

View File

@ -52,6 +52,7 @@ use std::cell::{Cell, RefCell};
use std::cmp; use std::cmp;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::iter; use std::iter;
use std::ops::ControlFlow;
pub use rustc_middle::traits::select::*; pub use rustc_middle::traits::select::*;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
@ -1592,71 +1593,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx.selection_cache.insert((param_env, pred), dep_node, candidate); self.infcx.selection_cache.insert((param_env, pred), dep_node, candidate);
} }
/// Matches a predicate against the bounds of its self type. /// Looks at the item bounds of the projection or opaque type.
/// /// If this is a nested rigid projection, such as
/// Given an obligation like `<T as Foo>::Bar: Baz` where the self type is /// `<<T as Tr1>::Assoc as Tr2>::Assoc`, consider the item bounds
/// a projection, look at the bounds of `T::Bar`, see if we can find a /// on both `Tr1::Assoc` and `Tr2::Assoc`, since we may encounter
/// `Baz` bound. We return indexes into the list returned by /// relative bounds on both via the `associated_type_bounds` feature.
/// `tcx.item_bounds` for any applicable bounds. pub(super) fn for_each_item_bound<T>(
#[instrument(level = "debug", skip(self), ret)]
fn match_projection_obligation_against_definition_bounds(
&mut self, &mut self,
obligation: &PolyTraitObligation<'tcx>, mut self_ty: Ty<'tcx>,
) -> smallvec::SmallVec<[usize; 2]> { mut for_each: impl FnMut(&mut Self, ty::Clause<'tcx>, usize) -> ControlFlow<T, ()>,
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); on_ambiguity: impl FnOnce(),
let placeholder_trait_predicate = ) -> ControlFlow<T, ()> {
self.infcx.enter_forall_and_leak_universe(poly_trait_predicate); let mut idx = 0;
debug!(?placeholder_trait_predicate); loop {
let (kind, alias_ty) = match *self_ty.kind() {
let tcx = self.infcx.tcx; ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty),
let (def_id, args) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() { ty::Infer(ty::TyVar(_)) => {
ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => { on_ambiguity();
(def_id, args) return ControlFlow::Continue(());
}
_ => {
span_bug!(
obligation.cause.span,
"match_projection_obligation_against_definition_bounds() called \
but self-ty is not a projection: {:?}",
placeholder_trait_predicate.trait_ref.self_ty()
);
}
};
let bounds = tcx.item_bounds(def_id).instantiate(tcx, args);
// 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();
bounds
.iter()
.enumerate()
.filter_map(|(idx, bound)| {
let bound_predicate = bound.kind();
if let ty::ClauseKind::Trait(pred) = bound_predicate.skip_binder() {
let bound = bound_predicate.rebind(pred.trait_ref);
if self.infcx.probe(|_| {
match self.match_normalize_trait_ref(
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 _ => return ControlFlow::Continue(()),
}) };
.collect()
for bound in
self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args)
{
for_each(self, bound, idx)?;
idx += 1;
}
if kind == ty::Projection {
self_ty = alias_ty.self_ty();
} else {
return ControlFlow::Continue(());
}
}
} }
/// Equates the trait in `obligation` with trait bound. If the two traits /// Equates the trait in `obligation` with trait bound. If the two traits

View File

@ -191,6 +191,20 @@ pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [ast:
cx.tcx.get_attrs_unchecked(did) cx.tcx.get_attrs_unchecked(did)
} }
pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<Symbol> {
tcx.def_path(def_id)
.data
.into_iter()
.filter_map(|elem| {
// extern blocks (and a few others things) have an empty name.
match elem.data.get_opt_name() {
Some(s) if !s.is_empty() => Some(s),
_ => None,
}
})
.collect()
}
/// Record an external fully qualified name in the external_paths cache. /// Record an external fully qualified name in the external_paths cache.
/// ///
/// These names are used later on by HTML rendering to generate things like /// These names are used later on by HTML rendering to generate things like
@ -206,8 +220,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT
let crate_name = cx.tcx.crate_name(did.krate); let crate_name = cx.tcx.crate_name(did.krate);
let relative = let relative = item_relative_path(cx.tcx, did);
cx.tcx.def_path(did).data.into_iter().filter_map(|elem| elem.data.get_opt_name());
let fqn = if let ItemType::Macro = kind { let fqn = if let ItemType::Macro = kind {
// Check to see if it is a macro 2.0 or built-in macro // Check to see if it is a macro 2.0 or built-in macro
if matches!( if matches!(
@ -218,7 +231,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT
) { ) {
once(crate_name).chain(relative).collect() once(crate_name).chain(relative).collect()
} else { } else {
vec![crate_name, relative.last().expect("relative was empty")] vec![crate_name, *relative.last().expect("relative was empty")]
} }
} else { } else {
once(crate_name).chain(relative).collect() once(crate_name).chain(relative).collect()

View File

@ -4,7 +4,7 @@ use std::fmt;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use rustc_hir::def::DefKind; use rustc_hir::def::{CtorOf, DefKind};
use rustc_span::hygiene::MacroKind; use rustc_span::hygiene::MacroKind;
use crate::clean; use crate::clean;
@ -115,7 +115,15 @@ impl<'a> From<&'a clean::Item> for ItemType {
impl From<DefKind> for ItemType { impl From<DefKind> for ItemType {
fn from(other: DefKind) -> Self { fn from(other: DefKind) -> Self {
match other { Self::from_def_kind(other, None)
}
}
impl ItemType {
/// Depending on the parent kind, some variants have a different translation (like a `Method`
/// becoming a `TyMethod`).
pub(crate) fn from_def_kind(kind: DefKind, parent_kind: Option<DefKind>) -> Self {
match kind {
DefKind::Enum => Self::Enum, DefKind::Enum => Self::Enum,
DefKind::Fn => Self::Function, DefKind::Fn => Self::Function,
DefKind::Mod => Self::Module, DefKind::Mod => Self::Module,
@ -131,30 +139,35 @@ impl From<DefKind> for ItemType {
MacroKind::Attr => ItemType::ProcAttribute, MacroKind::Attr => ItemType::ProcAttribute,
MacroKind::Derive => ItemType::ProcDerive, MacroKind::Derive => ItemType::ProcDerive,
}, },
DefKind::ForeignTy DefKind::ForeignTy => Self::ForeignType,
| DefKind::Variant DefKind::Variant => Self::Variant,
| DefKind::AssocTy DefKind::Field => Self::StructField,
| DefKind::TyParam DefKind::AssocTy => Self::AssocType,
DefKind::AssocFn => {
if let Some(DefKind::Trait) = parent_kind {
Self::TyMethod
} else {
Self::Method
}
}
DefKind::Ctor(CtorOf::Struct, _) => Self::Struct,
DefKind::Ctor(CtorOf::Variant, _) => Self::Variant,
DefKind::AssocConst => Self::AssocConst,
DefKind::TyParam
| DefKind::ConstParam | DefKind::ConstParam
| DefKind::Ctor(..)
| DefKind::AssocFn
| DefKind::AssocConst
| DefKind::ExternCrate | DefKind::ExternCrate
| DefKind::Use | DefKind::Use
| DefKind::ForeignMod | DefKind::ForeignMod
| DefKind::AnonConst | DefKind::AnonConst
| DefKind::InlineConst | DefKind::InlineConst
| DefKind::OpaqueTy | DefKind::OpaqueTy
| DefKind::Field
| DefKind::LifetimeParam | DefKind::LifetimeParam
| DefKind::GlobalAsm | DefKind::GlobalAsm
| DefKind::Impl { .. } | DefKind::Impl { .. }
| DefKind::Closure => Self::ForeignType, | DefKind::Closure => Self::ForeignType,
} }
} }
}
impl ItemType {
pub(crate) fn as_str(&self) -> &'static str { pub(crate) fn as_str(&self) -> &'static str {
match *self { match *self {
ItemType::Module => "mod", ItemType::Module => "mod",

View File

@ -32,6 +32,7 @@ use crate::clean::{
self, types::ExternalLocation, utils::find_nearest_parent_module, ExternalCrate, ItemId, self, types::ExternalLocation, utils::find_nearest_parent_module, ExternalCrate, ItemId,
PrimitiveType, PrimitiveType,
}; };
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType; use crate::formats::item_type::ItemType;
use crate::html::escape::Escape; use crate::html::escape::Escape;
use crate::html::render::Context; use crate::html::render::Context;
@ -581,22 +582,11 @@ fn generate_macro_def_id_path(
cx: &Context<'_>, cx: &Context<'_>,
root_path: Option<&str>, root_path: Option<&str>,
) -> Result<(String, ItemType, Vec<Symbol>), HrefError> { ) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
let tcx = cx.shared.tcx; let tcx = cx.tcx();
let crate_name = tcx.crate_name(def_id.krate); let crate_name = tcx.crate_name(def_id.krate);
let cache = cx.cache(); let cache = cx.cache();
let fqp: Vec<Symbol> = tcx let fqp = clean::inline::item_relative_path(tcx, def_id);
.def_path(def_id)
.data
.into_iter()
.filter_map(|elem| {
// extern blocks (and a few others things) have an empty name.
match elem.data.get_opt_name() {
Some(s) if !s.is_empty() => Some(s),
_ => None,
}
})
.collect();
let mut relative = fqp.iter().copied(); let mut relative = fqp.iter().copied();
let cstore = CStore::from_tcx(tcx); let cstore = CStore::from_tcx(tcx);
// We need this to prevent a `panic` when this function is used from intra doc links... // We need this to prevent a `panic` when this function is used from intra doc links...
@ -651,76 +641,82 @@ fn generate_macro_def_id_path(
Ok((url, ItemType::Macro, fqp)) Ok((url, ItemType::Macro, fqp))
} }
pub(crate) fn href_with_root_path( fn generate_item_def_id_path(
did: DefId, mut def_id: DefId,
original_def_id: DefId,
cx: &Context<'_>, cx: &Context<'_>,
root_path: Option<&str>, root_path: Option<&str>,
original_def_kind: DefKind,
) -> Result<(String, ItemType, Vec<Symbol>), HrefError> { ) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
use crate::rustc_trait_selection::infer::TyCtxtInferExt;
use crate::rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_middle::traits::ObligationCause;
let tcx = cx.tcx(); let tcx = cx.tcx();
let def_kind = tcx.def_kind(did); let crate_name = tcx.crate_name(def_id.krate);
let did = match def_kind {
DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant => { // No need to try to infer the actual parent item if it's not an associated item from the `impl`
// documented on their parent's page // block.
tcx.parent(did) if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) {
} let infcx = tcx.infer_ctxt().build();
DefKind::ExternCrate => { def_id = infcx
// Link to the crate itself, not the `extern crate` item. .at(&ObligationCause::dummy(), tcx.param_env(def_id))
if let Some(local_did) = did.as_local() { .query_normalize(ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity()))
tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id() .map(|resolved| infcx.resolve_vars_if_possible(resolved.value))
} else { .ok()
did .and_then(|normalized| normalized.skip_binder().ty_adt_def())
} .map(|adt| adt.did())
} .unwrap_or(def_id);
_ => did,
};
let cache = cx.cache();
let relative_to = &cx.current;
fn to_module_fqp(shortty: ItemType, fqp: &[Symbol]) -> &[Symbol] {
if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] }
} }
if !did.is_local() let relative = clean::inline::item_relative_path(tcx, def_id);
&& !cache.effective_visibilities.is_directly_public(tcx, did) let fqp: Vec<Symbol> = once(crate_name).chain(relative).collect();
&& !cache.document_private
&& !cache.primitive_locations.values().any(|&id| id == did)
{
return Err(HrefError::Private);
}
let def_kind = tcx.def_kind(def_id);
let shortty = def_kind.into();
let module_fqp = to_module_fqp(shortty, &fqp);
let mut is_remote = false; let mut is_remote = false;
let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
Some(&(ref fqp, shortty)) => (fqp, shortty, { let url_parts = url_parts(cx.cache(), def_id, &module_fqp, &cx.current, &mut is_remote)?;
let module_fqp = to_module_fqp(shortty, fqp.as_slice()); let (url_parts, shortty, fqp) = make_href(root_path, shortty, url_parts, &fqp, is_remote)?;
debug!(?fqp, ?shortty, ?module_fqp); if def_id == original_def_id {
href_relative_parts(module_fqp, relative_to).collect() return Ok((url_parts, shortty, fqp));
}), }
None => { let kind = ItemType::from_def_kind(original_def_kind, Some(def_kind));
if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) { Ok((format!("{url_parts}#{kind}.{}", tcx.item_name(original_def_id)), shortty, fqp))
let module_fqp = to_module_fqp(shortty, fqp); }
(
fqp, fn to_module_fqp(shortty: ItemType, fqp: &[Symbol]) -> &[Symbol] {
shortty, if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] }
match cache.extern_locations[&did.krate] { }
ExternalLocation::Remote(ref s) => {
is_remote = true; fn url_parts(
let s = s.trim_end_matches('/'); cache: &Cache,
let mut builder = UrlPartsBuilder::singleton(s); def_id: DefId,
builder.extend(module_fqp.iter().copied()); module_fqp: &[Symbol],
builder relative_to: &[Symbol],
} is_remote: &mut bool,
ExternalLocation::Local => { ) -> Result<UrlPartsBuilder, HrefError> {
href_relative_parts(module_fqp, relative_to).collect() match cache.extern_locations[&def_id.krate] {
} ExternalLocation::Remote(ref s) => {
ExternalLocation::Unknown => return Err(HrefError::DocumentationNotBuilt), *is_remote = true;
}, let s = s.trim_end_matches('/');
) let mut builder = UrlPartsBuilder::singleton(s);
} else if matches!(def_kind, DefKind::Macro(_)) { builder.extend(module_fqp.iter().copied());
return generate_macro_def_id_path(did, cx, root_path); Ok(builder)
} else {
return Err(HrefError::NotInExternalCache);
}
} }
}; ExternalLocation::Local => Ok(href_relative_parts(module_fqp, relative_to).collect()),
ExternalLocation::Unknown => Err(HrefError::DocumentationNotBuilt),
}
}
fn make_href(
root_path: Option<&str>,
shortty: ItemType,
mut url_parts: UrlPartsBuilder,
fqp: &[Symbol],
is_remote: bool,
) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
if !is_remote && let Some(root_path) = root_path { if !is_remote && let Some(root_path) = root_path {
let root = root_path.trim_end_matches('/'); let root = root_path.trim_end_matches('/');
url_parts.push_front(root); url_parts.push_front(root);
@ -739,6 +735,76 @@ pub(crate) fn href_with_root_path(
Ok((url_parts.finish(), shortty, fqp.to_vec())) Ok((url_parts.finish(), shortty, fqp.to_vec()))
} }
pub(crate) fn href_with_root_path(
original_did: DefId,
cx: &Context<'_>,
root_path: Option<&str>,
) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
let tcx = cx.tcx();
let def_kind = tcx.def_kind(original_did);
let did = match def_kind {
DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant => {
// documented on their parent's page
tcx.parent(original_did)
}
// If this a constructor, we get the parent (either a struct or a variant) and then
// generate the link for this item.
DefKind::Ctor(..) => return href_with_root_path(tcx.parent(original_did), cx, root_path),
DefKind::ExternCrate => {
// Link to the crate itself, not the `extern crate` item.
if let Some(local_did) = original_did.as_local() {
tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id()
} else {
original_did
}
}
_ => original_did,
};
let cache = cx.cache();
let relative_to = &cx.current;
if !original_did.is_local() {
// If we are generating an href for the "jump to def" feature, then the only case we want
// to ignore is if the item is `doc(hidden)` because we can't link to it.
if root_path.is_some() {
if tcx.is_doc_hidden(original_did) {
return Err(HrefError::Private);
}
} else if !cache.effective_visibilities.is_directly_public(tcx, did)
&& !cache.document_private
&& !cache.primitive_locations.values().any(|&id| id == did)
{
return Err(HrefError::Private);
}
}
let mut is_remote = false;
let (fqp, shortty, url_parts) = match cache.paths.get(&did) {
Some(&(ref fqp, shortty)) => (fqp, shortty, {
let module_fqp = to_module_fqp(shortty, fqp.as_slice());
debug!(?fqp, ?shortty, ?module_fqp);
href_relative_parts(module_fqp, relative_to).collect()
}),
None => {
// Associated items are handled differently with "jump to def". The anchor is generated
// directly here whereas for intra-doc links, we have some extra computation being
// performed there.
let def_id_to_get = if root_path.is_some() { original_did } else { did };
if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&def_id_to_get) {
let module_fqp = to_module_fqp(shortty, fqp);
(fqp, shortty, url_parts(cache, did, module_fqp, relative_to, &mut is_remote)?)
} else if matches!(def_kind, DefKind::Macro(_)) {
return generate_macro_def_id_path(did, cx, root_path);
} else if did.is_local() {
return Err(HrefError::Private);
} else {
return generate_item_def_id_path(did, original_did, cx, root_path, def_kind);
}
}
};
make_href(root_path, shortty, url_parts, fqp, is_remote)
}
pub(crate) fn href( pub(crate) fn href(
did: DefId, did: DefId,
cx: &Context<'_>, cx: &Context<'_>,

View File

@ -14,8 +14,8 @@ use std::path::{Path, PathBuf};
// #73494. // #73494.
const ENTRY_LIMIT: usize = 900; const ENTRY_LIMIT: usize = 900;
// FIXME: The following limits should be reduced eventually. // FIXME: The following limits should be reduced eventually.
const ISSUES_ENTRY_LIMIT: usize = 1819; const ISSUES_ENTRY_LIMIT: usize = 1794;
const ROOT_ENTRY_LIMIT: usize = 872; const ROOT_ENTRY_LIMIT: usize = 870;
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
"rs", // test source files "rs", // test source files

View File

@ -0,0 +1,48 @@
// compile-flags: -Zunstable-options --generate-link-to-definition
#![crate_name = "foo"]
// @has 'src/foo/jump-to-non-local-method.rs.html'
// @has - '//a[@href="{{channel}}/core/sync/atomic/struct.AtomicIsize.html"]' 'std::sync::atomic::AtomicIsize'
use std::sync::atomic::AtomicIsize;
// @has - '//a[@href="{{channel}}/std/io/trait.Read.html"]' 'std::io::Read'
use std::io::Read;
// @has - '//a[@href="{{channel}}/std/io/index.html"]' 'std::io'
use std::io;
// @has - '//a[@href="{{channel}}/std/process/fn.exit.html"]' 'std::process::exit'
use std::process::exit;
use std::cmp::Ordering;
use std::marker::PhantomData;
pub fn bar2<T: Read>(readable: T) {
// @has - '//a[@href="{{channel}}/std/io/trait.Read.html#tymethod.read"]' 'read'
let _ = readable.read(&mut []);
}
pub fn bar() {
// @has - '//a[@href="{{channel}}/core/sync/atomic/struct.AtomicIsize.html#method.new"]' 'AtomicIsize::new'
let _ = AtomicIsize::new(0);
// @has - '//a[@href="#48"]' 'local_private'
local_private();
}
pub fn extern_call() {
// @has - '//a[@href="{{channel}}/std/process/fn.exit.html"]' 'exit'
exit(0);
}
pub fn macro_call() -> Result<(), ()> {
// @has - '//a[@href="{{channel}}/core/macro.try.html"]' 'try!'
try!(Err(()));
Ok(())
}
pub fn variant() {
// @has - '//a[@href="{{channel}}/core/cmp/enum.Ordering.html#variant.Less"]' 'Ordering::Less'
let _ = Ordering::Less;
// @has - '//a[@href="{{channel}}/core/marker/struct.PhantomData.html"]' 'PhantomData'
let _: PhantomData::<usize> = PhantomData;
}
fn local_private() {}

View File

@ -1,5 +1,4 @@
// NOTE: rustc cannot currently handle bounds of the form `for<'a> <Foo as Bar<'a>>::Assoc: Baz`. // check-pass
// This should hopefully be fixed with Chalk.
#![feature(associated_type_bounds)] #![feature(associated_type_bounds)]
@ -24,9 +23,6 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 {
trait Case1 { 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; pub struct S1;
@ -35,33 +31,17 @@ impl Case1 for S1 {
} }
fn assume_case1<T: Case1>() { fn assume_case1<T: Case1>() {
fn assert_a<_0, A>() fn assert_c<_1, _2, C>()
where
A: Iterator<Item = _0>,
_0: Debug,
{
}
assert_a::<_, T::A>();
fn assert_b<_0, B>()
where
B: Iterator<Item = _0>,
_0: 'static,
{
}
assert_b::<_, T::B>();
fn assert_c<_0, _1, _2, C>()
where where
C: Clone + Iterator<Item = _2>, C: Clone + Iterator<Item = _2>,
_2: Send + Iterator<Item = _1>, _2: Send + Iterator<Item = _1>,
_1: for<'a> Lam<&'a u8, App = _0>, _1: for<'a> Lam<&'a u8>,
_0: Debug, for<'a> <_1 as Lam<&'a u8>>::App: Debug,
{ {
} }
assert_c::<_, _, _, T::C>(); assert_c::<_, _, T::C>();
} }
fn main() { fn main() {
assume_case1(S1); assume_case1::<S1>();
} }

View File

@ -1,39 +0,0 @@
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
|
= help: the trait `Send` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
help: consider further restricting the associated type
|
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
| ++++++++++++++++++++++++++++++++++++++++++++++++++
error[E0277]: `<<Self as Case1>::C as Iterator>::Item` is not an iterator
--> $DIR/bad-bounds-on-assoc-in-trait.rs:26:43
|
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 `Iterator` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
help: consider further restricting the associated type
|
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 | 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
|
= help: the trait `Sync` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
help: consider further restricting the associated type
|
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync {
| ++++++++++++++++++++++++++++++++++++++++++++++++++
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,3 +1,5 @@
// check-pass
#![feature(associated_type_bounds)] #![feature(associated_type_bounds)]
use std::fmt::Debug; use std::fmt::Debug;
@ -16,8 +18,6 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; }
trait Case1 { trait Case1 {
type A: Iterator<Item: Debug>; type A: Iterator<Item: Debug>;
//~^ ERROR `<<Self as Case1>::A as Iterator>::Item` doesn't implement `Debug`
type B: Iterator<Item: 'static>; type B: Iterator<Item: 'static>;
} }
@ -33,7 +33,6 @@ impl Case1 for S1 {
// bounds of `Out`, but trait selection can't find the bound since it applies // bounds of `Out`, but trait selection can't find the bound since it applies
// to a type other than `Self::Out`. // to a type other than `Self::Out`.
pub trait Foo { type Out: Baz<Assoc: Default>; } 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; } pub trait Baz { type Assoc; }
#[derive(Default)] #[derive(Default)]

View File

@ -1,26 +0,0 @@
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`
|
= 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`
|
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`.

View File

@ -251,13 +251,10 @@ where
trait TRA1 { trait TRA1 {
type A: Iterator<Item: Copy, Item: Send>; type A: Iterator<Item: Copy, Item: Send>;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR `<<Self as TRA1>::A as Iterator>::Item` cannot be sent between threads safely
//~| ERROR the trait bound `<<Self as TRA1>::A as Iterator>::Item: Copy` is not satisfied
} }
trait TRA2 { trait TRA2 {
type A: Iterator<Item: Copy, Item: Copy>; type A: Iterator<Item: Copy, Item: Copy>;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR the trait bound `<<Self as TRA2>::A as Iterator>::Item: Copy` is not satisfied
} }
trait TRA3 { trait TRA3 {
type A: Iterator<Item: 'static, Item: 'static>; type A: Iterator<Item: 'static, Item: 'static>;

View File

@ -7,7 +7,7 @@ LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> {
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:267:40 --> $DIR/duplicate.rs:264:40
| |
LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -15,7 +15,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:269:44 --> $DIR/duplicate.rs:266:44
| |
LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -23,7 +23,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:271:43 --> $DIR/duplicate.rs:268:43
| |
LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -523,7 +523,7 @@ LL | type A: Iterator<Item: Copy, Item: Send>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:258:34 --> $DIR/duplicate.rs:256:34
| |
LL | type A: Iterator<Item: Copy, Item: Copy>; LL | type A: Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -531,7 +531,7 @@ LL | type A: Iterator<Item: Copy, Item: Copy>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:263:37 --> $DIR/duplicate.rs:260:37
| |
LL | type A: Iterator<Item: 'static, Item: 'static>; LL | type A: Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -631,41 +631,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: the trait bound `<<Self as TRA1>::A as Iterator>::Item: Copy` is not satisfied error: aborting due to 75 previous errors
--> $DIR/duplicate.rs:252:28
|
LL | type A: Iterator<Item: Copy, Item: Send>;
| ^^^^ the trait `Copy` is not implemented for `<<Self as TRA1>::A as Iterator>::Item`
|
help: consider further restricting the associated type
|
LL | trait TRA1 where <<Self as TRA1>::A as Iterator>::Item: Copy {
| +++++++++++++++++++++++++++++++++++++++++++++++++
error[E0277]: `<<Self as TRA1>::A as Iterator>::Item` cannot be sent between threads safely Some errors have detailed explanations: E0282, E0719.
--> $DIR/duplicate.rs:252:40 For more information about an error, try `rustc --explain E0282`.
|
LL | type A: Iterator<Item: Copy, Item: Send>;
| ^^^^ `<<Self as TRA1>::A as Iterator>::Item` cannot be sent between threads safely
|
= help: the trait `Send` is not implemented for `<<Self as TRA1>::A as Iterator>::Item`
help: consider further restricting the associated type
|
LL | trait TRA1 where <<Self as TRA1>::A as Iterator>::Item: Send {
| +++++++++++++++++++++++++++++++++++++++++++++++++
error[E0277]: the trait bound `<<Self as TRA2>::A as Iterator>::Item: Copy` is not satisfied
--> $DIR/duplicate.rs:258:28
|
LL | type A: Iterator<Item: Copy, Item: Copy>;
| ^^^^ the trait `Copy` is not implemented for `<<Self as TRA2>::A as Iterator>::Item`
|
help: consider further restricting the associated type
|
LL | trait TRA2 where <<Self as TRA2>::A as Iterator>::Item: Copy {
| +++++++++++++++++++++++++++++++++++++++++++++++++
error: aborting due to 78 previous errors
Some errors have detailed explanations: E0277, E0282, E0719.
For more information about an error, try `rustc --explain E0277`.

View File

@ -0,0 +1,17 @@
// check-pass
#![feature(associated_type_bounds)]
trait A<'a> {
type Assoc: ?Sized;
}
impl<'a> A<'a> for () {
type Assoc = &'a ();
}
fn hello() -> impl for<'a> A<'a, Assoc: Sized> {
()
}
fn main() {}

View File

@ -0,0 +1,37 @@
// check-pass
#![feature(associated_type_bounds)]
trait Trait1 {
type Assoc1: Bar;
fn assoc(self) -> Self::Assoc1;
}
impl Trait1 for () {
type Assoc1 = ();
fn assoc(self) {}
}
trait Foo {}
impl Foo for () {}
trait Bar {}
impl Bar for () {}
fn hello() -> impl Trait1<Assoc1: Foo> {
()
}
fn world() {
// Tests that `Assoc1: Foo` bound in the RPIT doesn't disqualify
// the `Assoc1: Bar` bound in the item, as a nested RPIT desugaring
// would do.
fn is_foo(_: impl Foo) {}
is_foo(hello().assoc());
fn is_bar(_: impl Bar) {}
is_bar(hello().assoc());
}
fn main() {}

View File

@ -12,6 +12,10 @@ LL | trait X<'a>
LL | where LL | where
LL | for<'b> <Self as X<'b>>::U: Clone, LL | for<'b> <Self as X<'b>>::U: Clone,
| ^^^^^ required by this bound in `X` | ^^^^^ required by this bound in `X`
help: consider further restricting the associated type
|
LL | fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) where for<'b> <T as X<'b>>::U: Clone {
| ++++++++++++++++++++++++++++++++++++
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -1,5 +1,5 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/normalizing-self-auto-trait-issue-109924.rs:7:12 --> $DIR/normalizing-self-auto-trait-issue-109924.rs:6:12
| |
LL | #![feature(return_type_notation)] LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
@ -7,29 +7,5 @@ LL | #![feature(return_type_notation)]
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default = note: `#[warn(incomplete_features)]` on by default
error[E0277]: `impl Future<Output = ()> { <_ as Foo>::bar() }` cannot be sent between threads safely warning: 1 warning emitted
--> $DIR/normalizing-self-auto-trait-issue-109924.rs:22:11
|
LL | build(Bar);
| ----- ^^^ `impl Future<Output = ()> { <_ as Foo>::bar() }` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
= help: the trait `for<'a> Send` is not implemented for `impl Future<Output = ()> { <_ as Foo>::bar() }`
note: this is a known limitation of the trait solver that will be lifted in the future
--> $DIR/normalizing-self-auto-trait-issue-109924.rs:22:11
|
LL | build(Bar);
| ------^^^-
| | |
| | the trait solver is unable to infer the generic types that should be inferred from this argument
| add turbofish arguments to this call to specify the types manually, even if it's redundant
note: required by a bound in `build`
--> $DIR/normalizing-self-auto-trait-issue-109924.rs:19:39
|
LL | fn build<T>(_: T) where T: Foo<bar(): Send> {}
| ^^^^ required by this bound in `build`
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,5 +1,5 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/normalizing-self-auto-trait-issue-109924.rs:7:12 --> $DIR/normalizing-self-auto-trait-issue-109924.rs:6:12
| |
LL | #![feature(return_type_notation)] LL | #![feature(return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^

View File

@ -1,11 +1,10 @@
// check-pass
// revisions: current next // revisions: current next
//[current] known-bug: #109924
//[next] check-pass
//[next] compile-flags: -Znext-solver //[next] compile-flags: -Znext-solver
// edition:2021 // edition:2021
#![feature(return_type_notation)] #![feature(return_type_notation)]
//[next]~^ WARN the feature `return_type_notation` is incomplete //~^ WARN the feature `return_type_notation` is incomplete
trait Foo { trait Foo {
async fn bar(&self); async fn bar(&self);

View File

@ -1,11 +0,0 @@
// run-pass
#![allow(unused_imports)]
#![no_std]
extern crate std;
use std::ffi::c_void;
pub fn main() {
std::println!("Hello world!");
}

View File

@ -11,7 +11,6 @@ impl Tr1 for S1 { type As1 = S2; }
trait _Tr3 { trait _Tr3 {
type A: Iterator<Item: Copy>; type A: Iterator<Item: Copy>;
//~^ ERROR associated type bounds are unstable //~^ 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>; type B: Iterator<Item: 'static>;
//~^ ERROR associated type bounds are unstable //~^ ERROR associated type bounds are unstable

View File

@ -9,7 +9,7 @@ LL | type A: Iterator<Item: Copy>;
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:16:22 --> $DIR/feature-gate-associated_type_bounds.rs:15:22
| |
LL | type B: Iterator<Item: 'static>; LL | type B: Iterator<Item: 'static>;
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
@ -19,7 +19,7 @@ LL | type B: Iterator<Item: 'static>;
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:20:20 --> $DIR/feature-gate-associated_type_bounds.rs:19:20
| |
LL | struct _St1<T: Tr1<As1: Tr2>> { LL | struct _St1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^ | ^^^^^^^^
@ -29,7 +29,7 @@ LL | struct _St1<T: Tr1<As1: Tr2>> {
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:27:18 --> $DIR/feature-gate-associated_type_bounds.rs:26:18
| |
LL | enum _En1<T: Tr1<As1: Tr2>> { LL | enum _En1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^ | ^^^^^^^^
@ -39,7 +39,7 @@ LL | enum _En1<T: Tr1<As1: Tr2>> {
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:34:19 --> $DIR/feature-gate-associated_type_bounds.rs:33:19
| |
LL | union _Un1<T: Tr1<As1: Tr2>> { LL | union _Un1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^ | ^^^^^^^^
@ -49,7 +49,7 @@ LL | union _Un1<T: Tr1<As1: Tr2>> {
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:41:37 --> $DIR/feature-gate-associated_type_bounds.rs:40:37
| |
LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T; LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -59,7 +59,7 @@ LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:44:22 --> $DIR/feature-gate-associated_type_bounds.rs:43:22
| |
LL | fn _apit(_: impl Tr1<As1: Copy>) {} LL | fn _apit(_: impl Tr1<As1: Copy>) {}
| ^^^^^^^^^ | ^^^^^^^^^
@ -69,7 +69,7 @@ LL | fn _apit(_: impl Tr1<As1: Copy>) {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:46:26 --> $DIR/feature-gate-associated_type_bounds.rs:45:26
| |
LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {} LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
| ^^^^^^^^^ | ^^^^^^^^^
@ -79,7 +79,7 @@ LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:49:24 --> $DIR/feature-gate-associated_type_bounds.rs:48:24
| |
LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 } LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
| ^^^^^^^^^ | ^^^^^^^^^
@ -89,7 +89,7 @@ LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:52:31 --> $DIR/feature-gate-associated_type_bounds.rs:51:31
| |
LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) } LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
| ^^^^^^^^^ | ^^^^^^^^^
@ -99,7 +99,7 @@ LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:55:23 --> $DIR/feature-gate-associated_type_bounds.rs:54:23
| |
LL | const _cdef: impl Tr1<As1: Copy> = S1; LL | const _cdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^ | ^^^^^^^^^
@ -109,7 +109,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1;
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:61:24 --> $DIR/feature-gate-associated_type_bounds.rs:60:24
| |
LL | static _sdef: impl Tr1<As1: Copy> = S1; LL | static _sdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^ | ^^^^^^^^^
@ -119,7 +119,7 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1;
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: associated type bounds are unstable error[E0658]: associated type bounds are unstable
--> $DIR/feature-gate-associated_type_bounds.rs:68:21 --> $DIR/feature-gate-associated_type_bounds.rs:67:21
| |
LL | let _: impl Tr1<As1: Copy> = S1; LL | let _: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^ | ^^^^^^^^^
@ -129,7 +129,7 @@ LL | let _: impl Tr1<As1: Copy> = S1;
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0562]: `impl Trait` is not allowed in const types error[E0562]: `impl Trait` is not allowed in const types
--> $DIR/feature-gate-associated_type_bounds.rs:55:14 --> $DIR/feature-gate-associated_type_bounds.rs:54:14
| |
LL | const _cdef: impl Tr1<As1: Copy> = S1; LL | const _cdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -137,7 +137,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1;
= note: `impl Trait` is only allowed in arguments and return types of functions and methods = note: `impl Trait` is only allowed in arguments and return types of functions and methods
error[E0562]: `impl Trait` is not allowed in static types error[E0562]: `impl Trait` is not allowed in static types
--> $DIR/feature-gate-associated_type_bounds.rs:61:15 --> $DIR/feature-gate-associated_type_bounds.rs:60:15
| |
LL | static _sdef: impl Tr1<As1: Copy> = S1; LL | static _sdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -145,25 +145,14 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1;
= note: `impl Trait` is only allowed in arguments and return types of functions and methods = note: `impl Trait` is only allowed in arguments and return types of functions and methods
error[E0562]: `impl Trait` is not allowed in the type of variable bindings error[E0562]: `impl Trait` is not allowed in the type of variable bindings
--> $DIR/feature-gate-associated_type_bounds.rs:68:12 --> $DIR/feature-gate-associated_type_bounds.rs:67:12
| |
LL | let _: impl Tr1<As1: Copy> = S1; LL | let _: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
| |
= note: `impl Trait` is only allowed in arguments and return types of functions and methods = note: `impl Trait` is only allowed in arguments and return types of functions and methods
error[E0277]: the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied error: aborting due to 16 previous errors
--> $DIR/feature-gate-associated_type_bounds.rs:12:28
|
LL | type A: Iterator<Item: Copy>;
| ^^^^ the trait `Copy` is not implemented for `<<Self as _Tr3>::A as Iterator>::Item`
|
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`.

View File

@ -1,7 +1,4 @@
// check-fail // check-pass
// known-bug: #88460
// This should pass, but has a missed normalization due to HRTB.
pub trait Marker {} pub trait Marker {}

View File

@ -1,29 +0,0 @@
error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied
--> $DIR/issue-88460.rs:28:10
|
LL | test(Foo);
| ---- ^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>`
| |
| required by a bound introduced by this call
|
= help: the trait `Marker` is implemented for `()`
note: this is a known limitation of the trait solver that will be lifted in the future
--> $DIR/issue-88460.rs:28:10
|
LL | test(Foo);
| -----^^^-
| | |
| | the trait solver is unable to infer the generic types that should be inferred from this argument
| add turbofish arguments to this call to specify the types manually, even if it's redundant
note: required by a bound in `test`
--> $DIR/issue-88460.rs:15:27
|
LL | fn test<T>(value: T)
| ---- required by a bound in this function
...
LL | for<'a> T::Assoc<'a>: Marker,
| ^^^^^^ required by this bound in `test`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,5 +1,4 @@
// check-fail // check-pass
// known-bug: #90950
trait Yokeable<'a>: 'static { trait Yokeable<'a>: 'static {
type Output: 'a; type Output: 'a;

View File

@ -1,29 +0,0 @@
error[E0277]: the trait bound `for<'a> <_ as Yokeable<'a>>::Output: IsCovariant<'a>` is not satisfied
--> $DIR/issue-90950.rs:50:12
|
LL | upcast(y)
| ------ ^ the trait `for<'a> IsCovariant<'a>` is not implemented for `<_ as Yokeable<'a>>::Output`
| |
| required by a bound introduced by this call
|
= help: the trait `IsCovariant<'a>` is implemented for `std::borrow::Cow<'a, T>`
note: this is a known limitation of the trait solver that will be lifted in the future
--> $DIR/issue-90950.rs:50:12
|
LL | upcast(y)
| -------^-
| | |
| | the trait solver is unable to infer the generic types that should be inferred from this argument
| add turbofish arguments to this call to specify the types manually, even if it's redundant
note: required by a bound in `upcast`
--> $DIR/issue-90950.rs:27:42
|
LL | fn upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where
| ------ required by a bound in this function
LL | Y: for<'a> Yokeable<'a>,
LL | for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a>
| ^^^^^^^^^^^^^^^ required by this bound in `upcast`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,5 +1,4 @@
// check-fail // check-pass
// known-bug: #89196
// Should pass, but we normalize and check bounds before we resolve the generics // Should pass, but we normalize and check bounds before we resolve the generics
// of the function (which we know because of the return type). // of the function (which we know because of the return type).

View File

@ -1,23 +0,0 @@
error[E0277]: the trait bound `for<'a> <_ as Trait<'a>>::Out: Copy` is not satisfied
--> $DIR/norm-before-method-resolution.rs:22:17
|
LL | let _: () = weird_bound();
| ^^^^^^^^^^^^^ the trait `for<'a> Copy` is not implemented for `<_ as Trait<'a>>::Out`
|
note: this is a known limitation of the trait solver that will be lifted in the future
--> $DIR/norm-before-method-resolution.rs:22:17
|
LL | let _: () = weird_bound();
| ^^^^^^^^^^^^^ try adding turbofish arguments to this expression to specify the types manually, even if it's redundant
note: required by a bound in `weird_bound`
--> $DIR/norm-before-method-resolution.rs:18:40
|
LL | fn weird_bound<X>() -> X
| ----------- required by a bound in this function
...
LL | for<'a> <X as Trait<'a>>::Out: Copy
| ^^^^ required by this bound in `weird_bound`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,10 @@
// check-pass
// edition:2015
use {};
use {{}};
use ::{};
use {::{}};
fn main() {}

View File

@ -0,0 +1,10 @@
// check-pass
// edition:2018
use {};
use {{}};
use ::{};
use {::{}};
fn main() {}

View File

@ -1,9 +0,0 @@
// run-pass
// pretty-expanded FIXME #23616
#![allow(path_statements)]
pub fn main() {
let y: Box<_> = Box::new(1);
y;
}