Rollup merge of #106928 - bvanjoi:print-keyword-raw-identifier, r=petrochenkov
add raw identifier for keyword in suggestion
fix https://github.com/rust-lang/rust/issues/106841
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 9cf4d8c..82ff862 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -359,9 +359,9 @@
.insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
}
- OutlivesBound::RegionSubAlias(r_a, kind, alias_b) => {
+ OutlivesBound::RegionSubAlias(r_a, alias_b) => {
self.region_bound_pairs
- .insert(ty::OutlivesPredicate(GenericKind::Alias(kind, alias_b), r_a));
+ .insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
}
}
}
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 9031c04..ce72b78 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2602,7 +2602,7 @@
match path.res {
Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => {
// Check for desugared `impl Trait`.
- assert!(ty::is_impl_trait_defn(tcx, did).is_none());
+ assert!(tcx.is_type_alias_impl_trait(did));
let item_segment = path.segments.split_last().unwrap();
self.prohibit_generics(item_segment.1.iter(), |err| {
err.note("`impl Trait` types can't have type parameters");
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 35f47df..9be37db 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -76,6 +76,7 @@
is_foreign_item,
generator_kind,
collect_mod_item_types,
+ is_type_alias_impl_trait,
..*providers
};
}
@@ -1537,3 +1538,13 @@
_ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
}
}
+
+fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+ match tcx.hir().get_if_local(def_id) {
+ Some(Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. })) => {
+ matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias)
+ }
+ Some(_) => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
+ _ => bug!("tried getting opaque_ty_origin for non-local def-id {:?}", def_id),
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 3f691be..9459c5f 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -80,7 +80,7 @@
.or_insert(span);
}
- Component::Alias(kind, alias) => {
+ Component::Alias(alias_ty) => {
// This would either arise from something like:
//
// ```
@@ -99,13 +99,13 @@
//
// Here we want to add an explicit `where <T as Iterator>::Item: 'a`
// or `Opaque<T>: 'a` depending on the alias kind.
- let ty: Ty<'tcx> = tcx.mk_ty(ty::Alias(kind, alias));
+ let ty = alias_ty.to_ty(tcx);
required_predicates
.entry(ty::OutlivesPredicate(ty.into(), outlived_region))
.or_insert(span);
}
- Component::EscapingProjection(_) => {
+ Component::EscapingAlias(_) => {
// As above, but the projection involves
// late-bound regions. Therefore, the WF
// requirement is not checked in type definition
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index 16806fd..b3dd303 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -304,8 +304,8 @@
let mut reinit = None;
match expr.kind {
ExprKind::Assign(lhs, rhs, _) => {
- self.visit_expr(lhs);
self.visit_expr(rhs);
+ self.visit_expr(lhs);
reinit = Some(lhs);
}
@@ -433,7 +433,7 @@
self.drop_ranges.add_control_edge(self.expr_index, *target)
}),
- ExprKind::Break(destination, ..) => {
+ ExprKind::Break(destination, value) => {
// destination either points to an expression or to a block. We use
// find_target_expression_from_destination to use the last expression of the block
// if destination points to a block.
@@ -443,7 +443,11 @@
// will refer to the end of the block due to the post order traversal.
self.find_target_expression_from_destination(destination).map_or((), |target| {
self.drop_ranges.add_control_edge_hir_id(self.expr_index, target)
- })
+ });
+
+ if let Some(value) = value {
+ self.visit_expr(value);
+ }
}
ExprKind::Call(f, args) => {
@@ -465,6 +469,12 @@
ExprKind::AddrOf(..)
| ExprKind::Array(..)
+ // FIXME(eholk): We probably need special handling for AssignOps. The ScopeTree builder
+ // in region.rs runs both lhs then rhs and rhs then lhs and then sets all yields to be
+ // the latest they show up in either traversal. With the older scope-based
+ // approximation, this was fine, but it's probably not right now. What we probably want
+ // to do instead is still run both orders, but consider anything that showed up as a
+ // yield in either order.
| ExprKind::AssignOp(..)
| ExprKind::Binary(..)
| ExprKind::Block(..)
@@ -502,6 +512,9 @@
// Increment expr_count here to match what InteriorVisitor expects.
self.expr_index = self.expr_index + 1;
+
+ // Save a node mapping to get better CFG visualization
+ self.drop_ranges.add_node_mapping(pat.hir_id, self.expr_index);
}
}
@@ -521,7 +534,7 @@
}
});
}
- debug!("hir_id_map: {:?}", tracked_value_map);
+ debug!("hir_id_map: {:#?}", tracked_value_map);
let num_values = tracked_value_map.len();
Self {
tracked_value_map,
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
index c0a0bfe..e8d31be 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
@@ -2,6 +2,7 @@
//! flow graph when needed for debugging.
use rustc_graphviz as dot;
+use rustc_hir::{Expr, ExprKind, Node};
use rustc_middle::ty::TyCtxt;
use super::{DropRangesBuilder, PostOrderId};
@@ -80,10 +81,14 @@
.post_order_map
.iter()
.find(|(_hir_id, &post_order_id)| post_order_id == *n)
- .map_or("<unknown>".into(), |(hir_id, _)| self
- .tcx
- .hir()
- .node_to_string(*hir_id))
+ .map_or("<unknown>".into(), |(hir_id, _)| format!(
+ "{}{}",
+ self.tcx.hir().node_to_string(*hir_id),
+ match self.tcx.hir().find(*hir_id) {
+ Some(Node::Expr(Expr { kind: ExprKind::Yield(..), .. })) => " (yield)",
+ _ => "",
+ }
+ ))
)
.into(),
)
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 7990d95..7af5260 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -71,10 +71,8 @@
yield_data.expr_and_pat_count, self.expr_count, source_span
);
- if self.fcx.sess().opts.unstable_opts.drop_tracking
- && self
- .drop_ranges
- .is_dropped_at(hir_id, yield_data.expr_and_pat_count)
+ if self
+ .is_dropped_at_yield_location(hir_id, yield_data.expr_and_pat_count)
{
debug!("value is dropped at yield point; not recording");
return false;
@@ -173,6 +171,18 @@
}
}
}
+
+ /// If drop tracking is enabled, consult drop_ranges to see if a value is
+ /// known to be dropped at a yield point and therefore can be omitted from
+ /// the generator witness.
+ fn is_dropped_at_yield_location(&self, value_hir_id: HirId, yield_location: usize) -> bool {
+ // short-circuit if drop tracking is not enabled.
+ if !self.fcx.sess().opts.unstable_opts.drop_tracking {
+ return false;
+ }
+
+ self.drop_ranges.is_dropped_at(value_hir_id, yield_location)
+ }
}
pub fn resolve_interior<'a, 'tcx>(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 9c38eb6..28fd03b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2272,13 +2272,10 @@
let labeled_user_string = match bound_kind {
GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
- GenericKind::Alias(ty::Projection, ref p) => format!("the associated type `{}`", p),
- GenericKind::Alias(ty::Opaque, ref p) => {
- format!(
- "the opaque type `{}`",
- self.tcx.def_path_str_with_substs(p.def_id, p.substs)
- )
- }
+ GenericKind::Alias(ref p) => match p.kind(self.tcx) {
+ ty::AliasKind::Projection => format!("the associated type `{}`", p),
+ ty::AliasKind::Opaque => format!("the opaque type `{}`", p),
+ },
};
if let Some(SubregionOrigin::CompareImplItemObligation {
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index 37907d2..3d86279 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -22,7 +22,7 @@
// is not in a position to judge which is the best technique, so
// we just product the projection as a component and leave it to
// the consumer to decide (but see `EscapingProjection` below).
- Alias(ty::AliasKind, ty::AliasTy<'tcx>),
+ Alias(ty::AliasTy<'tcx>),
// In the case where a projection has escaping regions -- meaning
// regions bound within the type itself -- we always use
@@ -44,7 +44,7 @@
// projection, so that implied bounds code can avoid relying on
// them. This gives us room to improve the regionck reasoning in
// the future without breaking backwards compat.
- EscapingProjection(Vec<Component<'tcx>>),
+ EscapingAlias(Vec<Component<'tcx>>),
}
/// Push onto `out` all the things that must outlive `'a` for the condition
@@ -120,17 +120,6 @@
out.push(Component::Param(p));
}
- // Ignore lifetimes found in opaque types. Opaque types can
- // have lifetimes in their substs which their hidden type doesn't
- // actually use. If we inferred that an opaque type is outlived by
- // its parameter lifetimes, then we could prove that any lifetime
- // outlives any other lifetime, which is unsound.
- // See https://github.com/rust-lang/rust/issues/84305 for
- // more details.
- ty::Alias(ty::Opaque, data) => {
- out.push(Component::Alias(ty::Opaque, data));
- },
-
// For projections, we prefer to generate an obligation like
// `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
// regionck more ways to prove that it holds. However,
@@ -139,15 +128,15 @@
// trait-ref. Therefore, if we see any higher-ranked regions,
// we simply fallback to the most restrictive rule, which
// requires that `Pi: 'a` for all `i`.
- ty::Alias(ty::Projection, data) => {
- if !data.has_escaping_bound_vars() {
+ ty::Alias(_, alias_ty) => {
+ if !alias_ty.has_escaping_bound_vars() {
// best case: no escaping regions, so push the
// projection and skip the subtree (thus generating no
// constraints for Pi). This defers the choice between
// the rules OutlivesProjectionEnv,
// OutlivesProjectionTraitDef, and
// OutlivesProjectionComponents to regionck.
- out.push(Component::Alias(ty::Projection, data));
+ out.push(Component::Alias(alias_ty));
} else {
// fallback case: hard code
// OutlivesProjectionComponents. Continue walking
@@ -155,7 +144,7 @@
let mut subcomponents = smallvec![];
let mut subvisited = SsoHashSet::new();
compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
- out.push(Component::EscapingProjection(subcomponents.into_iter().collect()));
+ out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
}
}
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index 52c3d97..24e3c34 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -138,9 +138,9 @@
self.region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
}
- OutlivesBound::RegionSubAlias(r_a, kind, projection_b) => {
+ OutlivesBound::RegionSubAlias(r_a, alias_b) => {
self.region_bound_pairs
- .insert(ty::OutlivesPredicate(GenericKind::Alias(kind, projection_b), r_a));
+ .insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
}
OutlivesBound::RegionSubRegion(r_a, r_b) => {
if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 77de335..0194549 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -67,7 +67,6 @@
};
use crate::traits::{ObligationCause, ObligationCauseCode};
use rustc_data_structures::undo_log::UndoLogs;
-use rustc_hir::def_id::DefId;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitable};
@@ -266,10 +265,8 @@
Component::Param(param_ty) => {
self.param_ty_must_outlive(origin, region, *param_ty);
}
- Component::Alias(kind, data) => {
- self.alias_must_outlive(*kind, *data, origin, region)
- }
- Component::EscapingProjection(subcomponents) => {
+ Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty),
+ Component::EscapingAlias(subcomponents) => {
self.components_must_outlive(origin, &subcomponents, region, category);
}
Component::UnresolvedInferenceVariable(v) => {
@@ -285,61 +282,26 @@
}
}
+ #[instrument(level = "debug", skip(self))]
fn param_ty_must_outlive(
&mut self,
origin: infer::SubregionOrigin<'tcx>,
region: ty::Region<'tcx>,
param_ty: ty::ParamTy,
) {
- debug!(
- "param_ty_must_outlive(region={:?}, param_ty={:?}, origin={:?})",
- region, param_ty, origin
- );
-
- let generic = GenericKind::Param(param_ty);
let verify_bound = self.verify_bound.param_bound(param_ty);
- self.delegate.push_verify(origin, generic, region, verify_bound);
+ self.delegate.push_verify(origin, GenericKind::Param(param_ty), region, verify_bound);
}
#[instrument(level = "debug", skip(self))]
- fn alias_must_outlive(
- &mut self,
- kind: ty::AliasKind,
- data: ty::AliasTy<'tcx>,
- origin: infer::SubregionOrigin<'tcx>,
- region: ty::Region<'tcx>,
- ) {
- self.generic_must_outlive(
- origin,
- region,
- GenericKind::Alias(kind, data),
- data.def_id,
- data.substs,
- kind == ty::Opaque,
- |ty| match *ty.kind() {
- ty::Alias(filter_kind, ty::AliasTy { def_id, substs, .. })
- if kind == filter_kind =>
- {
- (def_id, substs)
- }
- _ => bug!("expected only projection types from env, not {:?}", ty),
- },
- );
- }
-
- #[instrument(level = "debug", skip(self, filter))]
- fn generic_must_outlive(
+ fn alias_ty_must_outlive(
&mut self,
origin: infer::SubregionOrigin<'tcx>,
region: ty::Region<'tcx>,
- generic: GenericKind<'tcx>,
- def_id: DefId,
- substs: SubstsRef<'tcx>,
- is_opaque: bool,
- filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>),
+ alias_ty: ty::AliasTy<'tcx>,
) {
// An optimization for a common case with opaque types.
- if substs.is_empty() {
+ if alias_ty.substs.is_empty() {
return;
}
@@ -361,14 +323,14 @@
// These are guaranteed to apply, no matter the inference
// results.
let trait_bounds: Vec<_> =
- self.verify_bound.declared_region_bounds(def_id, substs).collect();
+ self.verify_bound.declared_bounds_from_definition(alias_ty).collect();
debug!(?trait_bounds);
// Compute the bounds we can derive from the environment. This
// is an "approximate" match -- in some cases, these bounds
// may not apply.
- let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(generic);
+ let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty);
debug!(?approx_env_bounds);
// Remove outlives bounds that we get from the environment but
@@ -383,8 +345,8 @@
// If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait`
// will be invoked with `['b => ^1]` and so we will get `^1` returned.
let bound = bound_outlives.skip_binder();
- let (def_id, substs) = filter(bound.0);
- self.verify_bound.declared_region_bounds(def_id, substs).all(|r| r != bound.1)
+ let ty::Alias(_, alias_ty) = bound.0.kind() else { bug!("expected AliasTy") };
+ self.verify_bound.declared_bounds_from_definition(*alias_ty).all(|r| r != bound.1)
});
// If declared bounds list is empty, the only applicable rule is
@@ -401,12 +363,12 @@
// the problem is to add `T: 'r`, which isn't true. So, if there are no
// inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition.
- let needs_infer = substs.needs_infer();
- if approx_env_bounds.is_empty() && trait_bounds.is_empty() && (needs_infer || is_opaque) {
+ if approx_env_bounds.is_empty()
+ && trait_bounds.is_empty()
+ && (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque)
+ {
debug!("no declared bounds");
-
- self.substs_must_outlive(substs, origin, region);
-
+ self.substs_must_outlive(alias_ty.substs, origin, region);
return;
}
@@ -447,14 +409,9 @@
// projection outlive; in some cases, this may add insufficient
// edges into the inference graph, leading to inference failures
// even though a satisfactory solution exists.
- let verify_bound = self.verify_bound.projection_opaque_bounds(
- generic,
- def_id,
- substs,
- &mut Default::default(),
- );
- debug!("projection_must_outlive: pushing {:?}", verify_bound);
- self.delegate.push_verify(origin, generic, region, verify_bound);
+ let verify_bound = self.verify_bound.alias_bound(alias_ty, &mut Default::default());
+ debug!("alias_must_outlive: pushing {:?}", verify_bound);
+ self.delegate.push_verify(origin, GenericKind::Alias(alias_ty), region, verify_bound);
}
fn substs_must_outlive(
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 56695a8..94de9bc 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -1,11 +1,10 @@
use crate::infer::outlives::components::{compute_components_recursive, Component};
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::region_constraints::VerifyIfEq;
-use crate::infer::{GenericKind, VerifyBound};
+use crate::infer::VerifyBound;
use rustc_data_structures::sso::SsoHashSet;
-use rustc_hir::def_id::DefId;
use rustc_middle::ty::GenericArg;
-use rustc_middle::ty::{self, OutlivesPredicate, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
use smallvec::smallvec;
@@ -94,29 +93,26 @@
/// this list.
pub fn approx_declared_bounds_from_env(
&self,
- generic: GenericKind<'tcx>,
+ alias_ty: ty::AliasTy<'tcx>,
) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> {
- let projection_ty = generic.to_ty(self.tcx);
- let erased_projection_ty = self.tcx.erase_regions(projection_ty);
- self.declared_generic_bounds_from_env_for_erased_ty(erased_projection_ty)
+ let erased_alias_ty = self.tcx.erase_regions(alias_ty.to_ty(self.tcx));
+ self.declared_generic_bounds_from_env_for_erased_ty(erased_alias_ty)
}
#[instrument(level = "debug", skip(self, visited))]
- pub fn projection_opaque_bounds(
+ pub fn alias_bound(
&self,
- generic: GenericKind<'tcx>,
- def_id: DefId,
- substs: SubstsRef<'tcx>,
+ alias_ty: ty::AliasTy<'tcx>,
visited: &mut SsoHashSet<GenericArg<'tcx>>,
) -> VerifyBound<'tcx> {
- let generic_ty = generic.to_ty(self.tcx);
+ let alias_ty_as_ty = alias_ty.to_ty(self.tcx);
// Search the env for where clauses like `P: 'a`.
- let projection_opaque_bounds = self
- .approx_declared_bounds_from_env(generic)
+ let env_bounds = self
+ .approx_declared_bounds_from_env(alias_ty)
.into_iter()
.map(|binder| {
- if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == generic_ty {
+ if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == alias_ty_as_ty {
// Micro-optimize if this is an exact match (this
// occurs often when there are no region variables
// involved).
@@ -126,19 +122,19 @@
VerifyBound::IfEq(verify_if_eq_b)
}
});
- // Extend with bounds that we can find from the trait.
- let trait_bounds =
- self.declared_region_bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r));
+
+ // Extend with bounds that we can find from the definition.
+ let definition_bounds =
+ self.declared_bounds_from_definition(alias_ty).map(|r| VerifyBound::OutlivedBy(r));
// see the extensive comment in projection_must_outlive
let recursive_bound = {
let mut components = smallvec![];
- compute_components_recursive(self.tcx, generic_ty.into(), &mut components, visited);
+ compute_components_recursive(self.tcx, alias_ty_as_ty.into(), &mut components, visited);
self.bound_from_components(&components, visited)
};
- VerifyBound::AnyBound(projection_opaque_bounds.chain(trait_bounds).collect())
- .or(recursive_bound)
+ VerifyBound::AnyBound(env_bounds.chain(definition_bounds).collect()).or(recursive_bound)
}
fn bound_from_components(
@@ -149,10 +145,8 @@
let mut bounds = components
.iter()
.map(|component| self.bound_from_single_component(component, visited))
- .filter(|bound| {
- // Remove bounds that must hold, since they are not interesting.
- !bound.must_hold()
- });
+ // Remove bounds that must hold, since they are not interesting.
+ .filter(|bound| !bound.must_hold());
match (bounds.next(), bounds.next()) {
(Some(first), None) => first,
@@ -170,13 +164,8 @@
match *component {
Component::Region(lt) => VerifyBound::OutlivedBy(lt),
Component::Param(param_ty) => self.param_bound(param_ty),
- Component::Alias(kind, data) => self.projection_opaque_bounds(
- GenericKind::Alias(kind, data),
- data.def_id,
- data.substs,
- visited,
- ),
- Component::EscapingProjection(ref components) => {
+ Component::Alias(alias_ty) => self.alias_bound(alias_ty, visited),
+ Component::EscapingAlias(ref components) => {
self.bound_from_components(components, visited)
}
Component::UnresolvedInferenceVariable(v) => {
@@ -292,16 +281,15 @@
///
/// This is for simplicity, and because we are not really smart
/// enough to cope with such bounds anywhere.
- pub fn declared_region_bounds(
+ pub fn declared_bounds_from_definition(
&self,
- def_id: DefId,
- substs: SubstsRef<'tcx>,
+ alias_ty: ty::AliasTy<'tcx>,
) -> impl Iterator<Item = ty::Region<'tcx>> {
let tcx = self.tcx;
- let bounds = tcx.item_bounds(def_id);
+ let bounds = tcx.item_bounds(alias_ty.def_id);
trace!("{:#?}", bounds.0);
bounds
- .subst_iter(tcx, substs)
+ .subst_iter(tcx, alias_ty.substs)
.filter_map(|p| p.to_opt_type_outlives())
.filter_map(|p| p.no_bound_vars())
.map(|OutlivesPredicate(_, r)| r)
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index fda5ffe..0428481 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -167,7 +167,7 @@
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
pub enum GenericKind<'tcx> {
Param(ty::ParamTy),
- Alias(ty::AliasKind, ty::AliasTy<'tcx>),
+ Alias(ty::AliasTy<'tcx>),
}
/// Describes the things that some `GenericKind` value `G` is known to
@@ -746,10 +746,7 @@
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
GenericKind::Param(ref p) => write!(f, "{:?}", p),
- GenericKind::Alias(ty::Projection, ref p) => write!(f, "{:?}", p),
- GenericKind::Alias(ty::Opaque, ref p) => ty::tls::with(|tcx| {
- write!(f, "{}", tcx.def_path_str_with_substs(p.def_id, tcx.lift(p.substs).unwrap()))
- }),
+ GenericKind::Alias(ref p) => write!(f, "{:?}", p),
}
}
}
@@ -758,10 +755,7 @@
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
GenericKind::Param(ref p) => write!(f, "{}", p),
- GenericKind::Alias(ty::Projection, ref p) => write!(f, "{}", p),
- GenericKind::Alias(ty::Opaque, ref p) => ty::tls::with(|tcx| {
- write!(f, "{}", tcx.def_path_str_with_substs(p.def_id, tcx.lift(p.substs).unwrap()))
- }),
+ GenericKind::Alias(ref p) => write!(f, "{}", p),
}
}
}
@@ -770,7 +764,7 @@
pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self {
GenericKind::Param(ref p) => p.to_ty(tcx),
- GenericKind::Alias(kind, data) => tcx.mk_ty(ty::Alias(kind, data)),
+ GenericKind::Alias(ref p) => p.to_ty(tcx),
}
}
}
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 4ada7b2..cd5bde2 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -261,14 +261,15 @@
Component::UnresolvedInferenceVariable(_) => None,
- Component::Alias(kind, data) => {
- let ty = tcx.mk_ty(ty::Alias(kind, data));
+ Component::Alias(alias_ty) => {
+ // We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
+ // With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
- ty::OutlivesPredicate(ty, r_min),
+ ty::OutlivesPredicate(alias_ty.to_ty(tcx), r_min),
)))
}
- Component::EscapingProjection(_) => {
+ Component::EscapingAlias(_) => {
// We might be able to do more here, but we don't
// want to deal with escaping vars right now.
None
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index cb45193..0d924f2 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -223,6 +223,15 @@
generator_kind => { table }
trait_def => { table }
deduced_param_attrs => { table }
+ is_type_alias_impl_trait => {
+ debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
+ cdata
+ .root
+ .tables
+ .is_type_alias_impl_trait
+ .get(cdata, def_id.index)
+ .is_some()
+ }
collect_return_position_impl_trait_in_trait_tys => {
Ok(cdata
.root
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index a3d44fa..ab2ad79 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1512,8 +1512,11 @@
hir::ItemKind::Mod(ref m) => {
return self.encode_info_for_mod(item.owner_id.def_id, m);
}
- hir::ItemKind::OpaqueTy(..) => {
+ hir::ItemKind::OpaqueTy(ref opaque) => {
self.encode_explicit_item_bounds(def_id);
+ if matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias) {
+ self.tables.is_type_alias_impl_trait.set(def_id.index, ());
+ }
}
hir::ItemKind::Enum(..) => {
let adt_def = self.tcx.adt_def(def_id);
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 5b7b096..5066dbb 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -404,6 +404,8 @@
proc_macro: Table<DefIndex, MacroKind>,
module_reexports: Table<DefIndex, LazyArray<ModChild>>,
deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
+ // Slot is full when opaque is TAIT.
+ is_type_alias_impl_trait: Table<DefIndex, ()>,
trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>,
}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0ec6f48..6bbf7fa 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -177,6 +177,12 @@
separate_provide_extern
}
+ query is_type_alias_impl_trait(key: DefId) -> bool
+ {
+ desc { "determine whether the opaque is a type-alias impl trait" }
+ separate_provide_extern
+ }
+
query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
eval_always
desc { "running analysis passes on this crate" }
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 2a68315..615154a 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -213,5 +213,5 @@
pub enum OutlivesBound<'tcx> {
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
- RegionSubAlias(ty::Region<'tcx>, ty::AliasKind, ty::AliasTy<'tcx>),
+ RegionSubAlias(ty::Region<'tcx>, ty::AliasTy<'tcx>),
}
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index e32a7ee..24f3d1a 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -52,6 +52,7 @@
usize,
(),
u32,
+ bool,
std::string::String,
crate::metadata::ModChild,
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index a128e90..6a7b23e 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1245,19 +1245,34 @@
/// aka. `tcx.parent(def_id)`.
pub def_id: DefId,
- /// This field exists to prevent the creation of `ProjectionTy` without using
+ /// This field exists to prevent the creation of `AliasTy` without using
/// [TyCtxt::mk_alias_ty].
pub(super) _use_mk_alias_ty_instead: (),
}
impl<'tcx> AliasTy<'tcx> {
+ pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind {
+ match tcx.def_kind(self.def_id) {
+ DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection,
+ DefKind::OpaqueTy => ty::Opaque,
+ kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
+ }
+ }
+
+ pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ tcx.mk_ty(ty::Alias(self.kind(tcx), self))
+ }
+}
+
+/// The following methods work only with associated type projections.
+impl<'tcx> AliasTy<'tcx> {
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
DefKind::ImplTraitPlaceholder => {
tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
}
- kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
+ kind => bug!("expected a projection AliasTy; found {kind:?}"),
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 434f75d..5297148 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1350,6 +1350,7 @@
expected_trait_ref,
obligation.cause.code(),
found_node,
+ obligation.param_env,
)
} else {
let (closure_span, closure_arg_span, found) = found_did
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 195bbe9..39e50b2 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -283,6 +283,7 @@
expected: ty::PolyTraitRef<'tcx>,
cause: &ObligationCauseCode<'tcx>,
found_node: Option<Node<'_>>,
+ param_env: ty::ParamEnv<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
fn note_conflicting_closure_bounds(
@@ -1978,6 +1979,7 @@
expected: ty::PolyTraitRef<'tcx>,
cause: &ObligationCauseCode<'tcx>,
found_node: Option<Node<'_>>,
+ param_env: ty::ParamEnv<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
pub(crate) fn build_fn_sig_ty<'tcx>(
infcx: &InferCtxt<'tcx>,
@@ -2040,7 +2042,7 @@
self.note_conflicting_closure_bounds(cause, &mut err);
if let Some(found_node) = found_node {
- hint_missing_borrow(span, found, expected, found_node, &mut err);
+ hint_missing_borrow(self, param_env, span, found, expected, found_node, &mut err);
}
err
@@ -3747,6 +3749,8 @@
/// Add a hint to add a missing borrow or remove an unnecessary one.
fn hint_missing_borrow<'tcx>(
+ infcx: &InferCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
span: Span,
found: Ty<'tcx>,
expected: Ty<'tcx>,
@@ -3769,7 +3773,7 @@
// This could be a variant constructor, for example.
let Some(fn_decl) = found_node.fn_decl() else { return; };
- let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
+ let args = fn_decl.inputs.iter().map(|ty| ty);
fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
let mut refs = 0;
@@ -3785,21 +3789,34 @@
let mut to_borrow = Vec::new();
let mut remove_borrow = Vec::new();
- for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
+ for ((found_arg, expected_arg), arg) in found_args.zip(expected_args).zip(args) {
let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
- if found_ty == expected_ty {
+ if infcx.can_eq(param_env, found_ty, expected_ty).is_ok() {
if found_refs < expected_refs {
- to_borrow.push((arg_span, expected_arg.to_string()));
+ to_borrow.push((arg.span.shrink_to_lo(), "&".repeat(expected_refs - found_refs)));
} else if found_refs > expected_refs {
- remove_borrow.push((arg_span, expected_arg.to_string()));
+ let mut span = arg.span.shrink_to_lo();
+ let mut left = found_refs - expected_refs;
+ let mut ty = arg;
+ while let hir::TyKind::Ref(_, mut_ty) = &ty.kind && left > 0 {
+ span = span.with_hi(mut_ty.ty.span.lo());
+ ty = mut_ty.ty;
+ left -= 1;
+ }
+ let sugg = if left == 0 {
+ (span, String::new())
+ } else {
+ (arg.span, expected_arg.to_string())
+ };
+ remove_borrow.push(sugg);
}
}
}
if !to_borrow.is_empty() {
- err.multipart_suggestion(
+ err.multipart_suggestion_verbose(
"consider borrowing the argument",
to_borrow,
Applicability::MaybeIncorrect,
@@ -3807,7 +3824,7 @@
}
if !remove_borrow.is_empty() {
- err.multipart_suggestion(
+ err.multipart_suggestion_verbose(
"do not borrow the argument",
remove_borrow,
Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index b47a70b..12d4cb4 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -654,7 +654,7 @@
// All of the requirements on type parameters
// have already been checked for `impl Trait` in
// return position. We do need to check type-alias-impl-trait though.
- if ty::is_impl_trait_defn(self.tcx, def_id).is_none() {
+ if self.tcx.is_type_alias_impl_trait(def_id) {
let obligations = self.nominal_obligations(def_id, substs);
self.out.extend(obligations);
}
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index d457a4a..7d2d843 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -154,10 +154,8 @@
match component {
Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
- Component::Alias(kind, p) => {
- Some(OutlivesBound::RegionSubAlias(sub_region, kind, p))
- }
- Component::EscapingProjection(_) =>
+ Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
+ Component::EscapingAlias(_) =>
// If the projection has escaping regions, don't
// try to infer any implied bounds even for its
// free components. This is conservative, because
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index ca3e991..bc8bada 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -138,7 +138,7 @@
Ok((ret, krates))
}
- /// Read a file and return all lines that match the <code>"{crate}":{data},\ </code> format,
+ /// Read a file and return all lines that match the <code>"{crate}":{data},\</code> format,
/// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
///
/// This forms the payload of files that look like this:
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 7db4703..22068eb 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -5,10 +5,8 @@
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{walk_item, Visitor};
use rustc_hir::Node;
use rustc_hir::CRATE_HIR_ID;
-use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
use rustc_span::symbol::{kw, sym, Symbol};
@@ -59,6 +57,9 @@
false
}
+// Also, is there some reason that this doesn't use the 'visit'
+// framework from syntax?.
+
pub(crate) struct RustdocVisitor<'a, 'tcx> {
cx: &'a mut core::DocContext<'tcx>,
view_item_stack: FxHashSet<hir::HirId>,
@@ -66,7 +67,6 @@
/// Are the current module and all of its parents public?
inside_public_path: bool,
exact_paths: FxHashMap<DefId, Vec<Symbol>>,
- modules: Vec<Module<'tcx>>,
}
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -74,19 +74,12 @@
// If the root is re-exported, terminate all recursion.
let mut stack = FxHashSet::default();
stack.insert(hir::CRATE_HIR_ID);
- let om = Module::new(
- cx.tcx.crate_name(LOCAL_CRATE),
- hir::CRATE_HIR_ID,
- cx.tcx.hir().root_module().spans.inner_span,
- );
-
RustdocVisitor {
cx,
view_item_stack: stack,
inlining: false,
inside_public_path: true,
exact_paths: FxHashMap::default(),
- modules: vec![om],
}
}
@@ -96,10 +89,12 @@
}
pub(crate) fn visit(mut self) -> Module<'tcx> {
- let root_module = self.cx.tcx.hir().root_module();
- self.visit_mod_contents(CRATE_HIR_ID, root_module);
-
- let mut top_level_module = self.modules.pop().unwrap();
+ let mut top_level_module = self.visit_mod_contents(
+ hir::CRATE_HIR_ID,
+ self.cx.tcx.hir().root_module(),
+ self.cx.tcx.crate_name(LOCAL_CRATE),
+ None,
+ );
// `#[macro_export] macro_rules!` items are reexported at the top level of the
// crate, regardless of where they're defined. We want to document the
@@ -114,13 +109,15 @@
// macro in the same module.
let mut inserted = FxHashSet::default();
for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) {
- if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
- let Some(local_def_id) = def_id.as_local() &&
- self.cx.tcx.has_attr(def_id, sym::macro_export) &&
- inserted.insert(def_id)
- {
- let item = self.cx.tcx.hir().expect_item(local_def_id);
- top_level_module.items.push((item, None, None));
+ if let Res::Def(DefKind::Macro(_), def_id) = export.res {
+ if let Some(local_def_id) = def_id.as_local() {
+ if self.cx.tcx.has_attr(def_id, sym::macro_export) {
+ if inserted.insert(def_id) {
+ let item = self.cx.tcx.hir().expect_item(local_def_id);
+ top_level_module.items.push((item, None, None));
+ }
+ }
+ }
}
}
@@ -154,23 +151,24 @@
top_level_module
}
- /// This method will go through the given module items in two passes:
- /// 1. The items which are not glob imports/reexports.
- /// 2. The glob imports/reexports.
- fn visit_mod_contents(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>) {
- debug!("Going through module {:?}", m);
+ fn visit_mod_contents(
+ &mut self,
+ id: hir::HirId,
+ m: &'tcx hir::Mod<'tcx>,
+ name: Symbol,
+ parent_id: Option<hir::HirId>,
+ ) -> Module<'tcx> {
+ let mut om = Module::new(name, id, m.spans.inner_span);
let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
// Keep track of if there were any private modules in the path.
let orig_inside_public_path = self.inside_public_path;
self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public();
-
- // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
- // the second loop):
for &i in m.item_ids {
let item = self.cx.tcx.hir().item(i);
- if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
- self.visit_item(item);
+ if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+ continue;
}
+ self.visit_item(item, None, &mut om, parent_id);
}
for &i in m.item_ids {
let item = self.cx.tcx.hir().item(i);
@@ -178,10 +176,11 @@
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
// imported items appear last, then they'll be the ones that get discarded.
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
- self.visit_item(item);
+ self.visit_item(item, None, &mut om, parent_id);
}
}
self.inside_public_path = orig_inside_public_path;
+ om
}
/// Tries to resolve the target of a `pub use` statement and inlines the
@@ -199,6 +198,7 @@
res: Res,
renamed: Option<Symbol>,
glob: bool,
+ om: &mut Module<'tcx>,
please_inline: bool,
) -> bool {
debug!("maybe_inline_local res: {:?}", res);
@@ -249,20 +249,20 @@
let prev = mem::replace(&mut self.inlining, true);
for &i in m.item_ids {
let i = self.cx.tcx.hir().item(i);
- self.visit_item_inner(i, None, Some(id));
+ self.visit_item(i, None, om, Some(id));
}
self.inlining = prev;
true
}
Node::Item(it) if !glob => {
let prev = mem::replace(&mut self.inlining, true);
- self.visit_item_inner(it, renamed, Some(id));
+ self.visit_item(it, renamed, om, Some(id));
self.inlining = prev;
true
}
Node::ForeignItem(it) if !glob => {
let prev = mem::replace(&mut self.inlining, true);
- self.visit_foreign_item_inner(it, renamed);
+ self.visit_foreign_item(it, renamed, om);
self.inlining = prev;
true
}
@@ -272,22 +272,13 @@
ret
}
- #[inline]
- fn add_to_current_mod(
+ fn visit_item(
&mut self,
item: &'tcx hir::Item<'_>,
renamed: Option<Symbol>,
+ om: &mut Module<'tcx>,
parent_id: Option<hir::HirId>,
) {
- self.modules.last_mut().unwrap().items.push((item, renamed, parent_id))
- }
-
- fn visit_item_inner(
- &mut self,
- item: &'tcx hir::Item<'_>,
- renamed: Option<Symbol>,
- parent_id: Option<hir::HirId>,
- ) -> bool {
debug!("visiting item {:?}", item);
let name = renamed.unwrap_or(item.ident.name);
@@ -302,7 +293,7 @@
hir::ItemKind::ForeignMod { items, .. } => {
for item in items {
let item = self.cx.tcx.hir().foreign_item(item.id);
- self.visit_foreign_item_inner(item, None);
+ self.visit_foreign_item(item, None, om);
}
}
// If we're inlining, skip private items or item reexported as "_".
@@ -335,13 +326,14 @@
res,
ident,
is_glob,
+ om,
please_inline,
) {
continue;
}
}
- self.add_to_current_mod(item, renamed, parent_id);
+ om.items.push((item, renamed, parent_id))
}
}
hir::ItemKind::Macro(ref macro_def, _) => {
@@ -361,11 +353,11 @@
let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
if is_macro_2_0 || nonexported || self.inlining {
- self.add_to_current_mod(item, renamed, None);
+ om.items.push((item, renamed, None));
}
}
hir::ItemKind::Mod(ref m) => {
- self.enter_mod(item.hir_id(), m, name);
+ om.mods.push(self.visit_mod_contents(item.hir_id(), m, name, parent_id));
}
hir::ItemKind::Fn(..)
| hir::ItemKind::ExternCrate(..)
@@ -376,92 +368,33 @@
| hir::ItemKind::OpaqueTy(..)
| hir::ItemKind::Static(..)
| hir::ItemKind::Trait(..)
- | hir::ItemKind::TraitAlias(..) => {
- self.add_to_current_mod(item, renamed, parent_id);
- }
+ | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
hir::ItemKind::Const(..) => {
// Underscore constants do not correspond to a nameable item and
// so are never useful in documentation.
if name != kw::Underscore {
- self.add_to_current_mod(item, renamed, parent_id);
+ om.items.push((item, renamed, parent_id));
}
}
hir::ItemKind::Impl(impl_) => {
// Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
// them up regardless of where they're located.
if !self.inlining && impl_.of_trait.is_none() {
- self.add_to_current_mod(item, None, None);
+ om.items.push((item, None, None));
}
}
}
- true
}
- fn visit_foreign_item_inner(
+ fn visit_foreign_item(
&mut self,
item: &'tcx hir::ForeignItem<'_>,
renamed: Option<Symbol>,
+ om: &mut Module<'tcx>,
) {
// If inlining we only want to include public functions.
if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() {
- self.modules.last_mut().unwrap().foreigns.push((item, renamed));
+ om.foreigns.push((item, renamed));
}
}
-
- /// This method will create a new module and push it onto the "modules stack" then call
- /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
- /// add into the list of modules of the current module.
- fn enter_mod(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, name: Symbol) {
- self.modules.push(Module::new(name, id, m.spans.inner_span));
-
- self.visit_mod_contents(id, m);
-
- let last = self.modules.pop().unwrap();
- self.modules.last_mut().unwrap().mods.push(last);
- }
-}
-
-// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
-// such as impl blocks in const blocks.
-impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
- type NestedFilter = nested_filter::All;
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.cx.tcx.hir()
- }
-
- fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
- let parent_id = if self.modules.len() > 1 {
- Some(self.modules[self.modules.len() - 2].id)
- } else {
- None
- };
- if self.visit_item_inner(i, None, parent_id) {
- walk_item(self, i);
- }
- }
-
- fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
- // Handled in `visit_item_inner`
- }
-
- fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId) {
- // Handled in `visit_item_inner`
- }
-
- fn visit_path(&mut self, _: &hir::Path<'tcx>, _: hir::HirId) {
- // Handled in `visit_item_inner`
- }
-
- fn visit_label(&mut self, _: &rustc_ast::Label) {
- // Unneeded.
- }
-
- fn visit_infer(&mut self, _: &hir::InferArg) {
- // Unneeded.
- }
-
- fn visit_lifetime(&mut self, _: &hir::Lifetime) {
- // Unneeded.
- }
}
diff --git a/src/tools/cargo b/src/tools/cargo
index a5d47a7..50eb688 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit a5d47a72595dd6fbe7d4e4f6ec20dc5fe724edd1
+Subproject commit 50eb688c2bbea5de5a2e8496230a7428798089d1
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index c5767a7..c49ecb1 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -426,10 +426,15 @@
self.known_bug = true;
} else {
panic!(
- "Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `unknown`."
+ "Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
);
}
+ } else if config.parse_name_directive(ln, KNOWN_BUG) {
+ panic!(
+ "Invalid known-bug attribute, requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
+ );
}
+
config.set_name_value_directive(ln, MIR_UNIT_TEST, &mut self.mir_unit_test, |s| {
s.trim().to_string()
});
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
index 939da18..4b1e042 100644
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
+++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
@@ -1,10 +1,12 @@
+// check-pass
// normalize-stderr-test: "`.*`" -> "`DEF_ID`"
// normalize-stdout-test: "`.*`" -> "`DEF_ID`"
// edition:2018
pub async fn f() -> impl std::fmt::Debug {
+ // rustdoc doesn't care that this is infinitely sized
#[derive(Debug)]
- enum E { //~ ERROR
+ enum E {
This(E),
Unit,
}
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
deleted file mode 100644
index aff7402..0000000
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0072]: recursive type `DEF_ID` has infinite size
- --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5
- |
-LL | enum E {
- | ^^^^^^
-LL | This(E),
- | - recursive without indirection
- |
-help: insert some indirection (e.g., a `DEF_ID`) to break the cycle
- |
-LL | This(Box<E>),
- | ++++ +
-
-error: aborting due to previous error
-
-For more information about this error, try `DEF_ID`.
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
index ac51725..ac79582 100644
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
+++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
@@ -1,5 +1,8 @@
+// check-pass
+
fn f() -> impl Sized {
- enum E { //~ ERROR
+ // rustdoc doesn't care that this is infinitely sized
+ enum E {
V(E),
}
unimplemented!()
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
deleted file mode 100644
index a61577b..0000000
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0072]: recursive type `f::E` has infinite size
- --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
- |
-LL | enum E {
- | ^^^^^^
-LL | V(E),
- | - recursive without indirection
- |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
- |
-LL | V(Box<E>),
- | ++++ +
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/rustdoc/impl-in-const-block.rs b/tests/rustdoc/impl-in-const-block.rs
deleted file mode 100644
index b44e713..0000000
--- a/tests/rustdoc/impl-in-const-block.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-// Regression test for #83026.
-// The goal of this test is to ensure that impl blocks inside
-// const expressions are documented as well.
-
-#![crate_name = "foo"]
-
-// @has 'foo/struct.A.html'
-// @has - '//*[@id="method.new"]/*[@class="code-header"]' 'pub fn new() -> A'
-// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'pub fn bar(&self)'
-// @has - '//*[@id="method.woo"]/*[@class="code-header"]' 'pub fn woo(&self)'
-// @has - '//*[@id="method.yoo"]/*[@class="code-header"]' 'pub fn yoo()'
-// @has - '//*[@id="method.yuu"]/*[@class="code-header"]' 'pub fn yuu()'
-pub struct A;
-
-const _: () = {
- impl A {
- const FOO: () = {
- impl A {
- pub fn woo(&self) {}
- }
- };
-
- pub fn new() -> A {
- A
- }
- }
-};
-pub const X: () = {
- impl A {
- pub fn bar(&self) {}
- }
-};
-
-fn foo() {
- impl A {
- pub fn yoo() {}
- }
- const _: () = {
- impl A {
- pub fn yuu() {}
- }
- };
-}
diff --git a/tests/ui/anonymous-higher-ranked-lifetime.stderr b/tests/ui/anonymous-higher-ranked-lifetime.stderr
index afb7f8f..c023d1b 100644
--- a/tests/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/tests/ui/anonymous-higher-ranked-lifetime.stderr
@@ -16,7 +16,7 @@
help: consider borrowing the argument
|
LL | f1(|_: &(), _: &()| {});
- | ~~~ ~~~
+ | + +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
@@ -35,8 +35,8 @@
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
help: consider borrowing the argument
|
-LL | f2(|_: &'a (), _: &()| {});
- | ~~~~~~ ~~~
+LL | f2(|_: &(), _: &()| {});
+ | + +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -56,7 +56,7 @@
help: consider borrowing the argument
|
LL | f3(|_: &(), _: &()| {});
- | ~~~ ~~~
+ | + +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
@@ -75,8 +75,8 @@
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
help: consider borrowing the argument
|
-LL | f4(|_: &(), _: &'r ()| {});
- | ~~~ ~~~~~~
+LL | f4(|_: &(), _: &()| {});
+ | + +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -95,17 +95,15 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
help: consider borrowing the argument
|
-LL | f5(|_: &'r (), _: &'r ()| {});
- | ~~~~~~ ~~~~~~
+LL | f5(|_: &(), _: &()| {});
+ | + +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
|
LL | g1(|_: (), _: ()| {});
- | ^^ --------------
- | | | |
- | | | help: consider borrowing the argument: `&()`
- | | found signature defined here
+ | ^^ -------------- found signature defined here
+ | |
| expected due to this
|
= note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -115,15 +113,17 @@
|
LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1`
+help: consider borrowing the argument
+ |
+LL | g1(|_: &(), _: ()| {});
+ | +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
|
LL | g2(|_: (), _: ()| {});
- | ^^ --------------
- | | | |
- | | | help: consider borrowing the argument: `&()`
- | | found signature defined here
+ | ^^ -------------- found signature defined here
+ | |
| expected due to this
|
= note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
@@ -133,15 +133,17 @@
|
LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
| ^^^^^^^^^^^^^^^^ required by this bound in `g2`
+help: consider borrowing the argument
+ |
+LL | g2(|_: &(), _: ()| {});
+ | +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
|
LL | g3(|_: (), _: ()| {});
- | ^^ --------------
- | | | |
- | | | help: consider borrowing the argument: `&'s ()`
- | | found signature defined here
+ | ^^ -------------- found signature defined here
+ | |
| expected due to this
|
= note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -151,15 +153,17 @@
|
LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3`
+help: consider borrowing the argument
+ |
+LL | g3(|_: &(), _: ()| {});
+ | +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
|
LL | g4(|_: (), _: ()| {});
- | ^^ --------------
- | | | |
- | | | help: consider borrowing the argument: `&()`
- | | found signature defined here
+ | ^^ -------------- found signature defined here
+ | |
| expected due to this
|
= note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
@@ -169,6 +173,10 @@
|
LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4`
+help: consider borrowing the argument
+ |
+LL | g4(|_: &(), _: ()| {});
+ | +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:11:5
@@ -188,7 +196,7 @@
help: consider borrowing the argument
|
LL | h1(|_: &(), _: (), _: &(), _: ()| {});
- | ~~~ ~~~
+ | + +
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -207,8 +215,8 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
help: consider borrowing the argument
|
-LL | h2(|_: &(), _: (), _: &'t0 (), _: ()| {});
- | ~~~ ~~~~~~~
+LL | h2(|_: &(), _: (), _: &(), _: ()| {});
+ | + +
error: aborting due to 11 previous errors
diff --git a/tests/ui/async-await/auxiliary/issue-107036.rs b/tests/ui/async-await/auxiliary/issue-107036.rs
new file mode 100644
index 0000000..c3f6141
--- /dev/null
+++ b/tests/ui/async-await/auxiliary/issue-107036.rs
@@ -0,0 +1,12 @@
+// edition:2021
+
+pub trait T {}
+impl T for () {}
+
+pub struct S {}
+
+impl S {
+ pub async fn f<'a>(&self) -> impl T + 'a {
+ ()
+ }
+}
diff --git a/tests/ui/async-await/await-sequence.rs b/tests/ui/async-await/await-sequence.rs
new file mode 100644
index 0000000..726c428
--- /dev/null
+++ b/tests/ui/async-await/await-sequence.rs
@@ -0,0 +1,21 @@
+// edition:2021
+// compile-flags: -Z drop-tracking
+// build-pass
+
+use std::collections::HashMap;
+
+fn main() {
+ let _ = real_main();
+}
+
+async fn nop() {}
+
+async fn real_main() {
+ nop().await;
+ nop().await;
+ nop().await;
+ nop().await;
+
+ let mut map: HashMap<(), ()> = HashMap::new();
+ map.insert((), nop().await);
+}
diff --git a/tests/ui/async-await/issue-107036.rs b/tests/ui/async-await/issue-107036.rs
new file mode 100644
index 0000000..6a22de2
--- /dev/null
+++ b/tests/ui/async-await/issue-107036.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-107036.rs
+// edition:2021
+// check-pass
+
+extern crate issue_107036;
+use issue_107036::S;
+
+async fn f() {
+ S{}.f().await;
+}
+
+fn main() {
+ let _ = f();
+}
diff --git a/tests/ui/chalkify/bugs/async.rs b/tests/ui/chalkify/bugs/async.rs
index 1c69b07..3169e47 100644
--- a/tests/ui/chalkify/bugs/async.rs
+++ b/tests/ui/chalkify/bugs/async.rs
@@ -1,7 +1,7 @@
-// check-fail
-// known-bug
+// edition:2021
+// known-bug: unknown
// unset-rustc-env:RUST_BACKTRACE
-// compile-flags:-Z trait-solver=chalk --edition=2021
+// compile-flags:-Z trait-solver=chalk
// error-pattern:internal compiler error
// failure-status:101
// normalize-stderr-test "DefId([^)]*)" -> "..."
diff --git a/tests/ui/closures/multiple-fn-bounds.stderr b/tests/ui/closures/multiple-fn-bounds.stderr
index da26302..32a1edb 100644
--- a/tests/ui/closures/multiple-fn-bounds.stderr
+++ b/tests/ui/closures/multiple-fn-bounds.stderr
@@ -2,10 +2,8 @@
--> $DIR/multiple-fn-bounds.rs:10:5
|
LL | foo(move |x| v);
- | ^^^ --------
- | | | |
- | | | help: do not borrow the argument: `char`
- | | found signature defined here
+ | ^^^ -------- found signature defined here
+ | |
| expected due to this
|
= note: expected closure signature `fn(char) -> _`
@@ -20,6 +18,10 @@
|
LL | fn foo<F: Fn(&char) -> bool + Fn(char) -> bool>(f: F) {
| ^^^^^^^^^^^^^^^^ required by this bound in `foo`
+help: do not borrow the argument
+ |
+LL | foo(move |char| v);
+ | ~~~~
error: aborting due to previous error
diff --git a/tests/ui/const-generics/issues/issue-85031-2.rs b/tests/ui/const-generics/issues/issue-85031-2.rs
index 4908fb2..50dd66d 100644
--- a/tests/ui/const-generics/issues/issue-85031-2.rs
+++ b/tests/ui/const-generics/issues/issue-85031-2.rs
@@ -1,5 +1,5 @@
// check-pass
-// known-bug
+// known-bug: unknown
// This should not compile, as the compiler should not know
// `A - 0` is satisfied `?x - 0` if `?x` is inferred to `A`.
@@ -10,7 +10,6 @@
impl<'a> Ref<'a> {
pub fn foo<const A: usize>() -> [(); A - 0] {
- //~^ WARN function cannot
Self::foo()
}
}
diff --git a/tests/ui/const-generics/issues/issue-85031-2.stderr b/tests/ui/const-generics/issues/issue-85031-2.stderr
index fc69057..896e1c7 100644
--- a/tests/ui/const-generics/issues/issue-85031-2.stderr
+++ b/tests/ui/const-generics/issues/issue-85031-2.stderr
@@ -3,7 +3,6 @@
|
LL | pub fn foo<const A: usize>() -> [(); A - 0] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
-LL |
LL | Self::foo()
| ----------- recursive call site
|
diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs
index 719d1bd..5101de1 100644
--- a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs
+++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs
@@ -1,5 +1,5 @@
// check-fail
-// known-bug
+// known-bug: unknown
// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for
// all 'a where I::Item<'a> is WF", but really means "for all 'a possible"
@@ -29,7 +29,6 @@
fn main() {
let slice = &mut ();
- //~^ temporary value dropped while borrowed
let windows = WindowsMut { slice };
print_items::<WindowsMut<'_>>(windows);
}
diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
index 1c9abc4..362aeae 100644
--- a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
+++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
@@ -3,7 +3,7 @@
|
LL | let slice = &mut ();
| ^^ creates a temporary value which is freed while still in use
-...
+LL | let windows = WindowsMut { slice };
LL | print_items::<WindowsMut<'_>>(windows);
| -------------------------------------- argument requires that borrow lasts for `'static`
LL | }
diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs
index 8e6c534..3174227 100644
--- a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs
+++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs
@@ -1,5 +1,5 @@
// check-fail
-// known-bug
+// known-bug: unknown
// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for
// all 'a where I::Item<'a> is WF", but really means "for all 'a possible"
@@ -16,7 +16,6 @@
{
let mut iter2 = Eat(iter, f);
let _next = iter2.next();
- //~^ borrowed data escapes
true
}
impl<I: LendingIterator> LendingIterator for &mut I {
diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.rs b/tests/ui/generic-associated-types/bugs/issue-100013.rs
index fc4e47a..973c548 100644
--- a/tests/ui/generic-associated-types/bugs/issue-100013.rs
+++ b/tests/ui/generic-associated-types/bugs/issue-100013.rs
@@ -1,5 +1,5 @@
// check-fail
-// known-bug
+// known-bug: unknown
// edition: 2021
// We really should accept this, but we need implied bounds between the regions
@@ -13,7 +13,6 @@
fn call<I: FutureIterator>() -> impl Send {
async { // a generator checked for autotrait impl `Send`
- //~^ lifetime bound not satisfied
let x = None::<I::Future<'_, '_>>; // a type referencing GAT
async {}.await; // a yield point
}
@@ -21,16 +20,13 @@
fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
async { // a generator checked for autotrait impl `Send`
- //~^ lifetime bound not satisfied
let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
- //~^ lifetime may not live long enough
async {}.await; // a yield point
}
}
fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
async { // a generator checked for autotrait impl `Send`
- //~^ lifetime bound not satisfied
let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
async {}.await; // a yield point
}
diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.stderr b/tests/ui/generic-associated-types/bugs/issue-100013.stderr
index 72ae288..9db124a 100644
--- a/tests/ui/generic-associated-types/bugs/issue-100013.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-100013.stderr
@@ -2,77 +2,73 @@
--> $DIR/issue-100013.rs:15:5
|
LL | / async { // a generator checked for autotrait impl `Send`
-LL | |
LL | | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
LL | | async {}.await; // a yield point
LL | | }
| |_____^
|
note: the lifetime defined here...
- --> $DIR/issue-100013.rs:17:38
+ --> $DIR/issue-100013.rs:16:38
|
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
| ^^
note: ...must outlive the lifetime defined here
- --> $DIR/issue-100013.rs:17:34
+ --> $DIR/issue-100013.rs:16:34
|
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
| ^^
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
error: lifetime bound not satisfied
- --> $DIR/issue-100013.rs:23:5
+ --> $DIR/issue-100013.rs:22:5
|
LL | / async { // a generator checked for autotrait impl `Send`
-LL | |
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
-LL | |
LL | | async {}.await; // a yield point
LL | | }
| |_____^
|
note: the lifetime defined here...
- --> $DIR/issue-100013.rs:22:14
+ --> $DIR/issue-100013.rs:21:14
|
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
| ^^
note: ...must outlive the lifetime defined here
- --> $DIR/issue-100013.rs:22:10
+ --> $DIR/issue-100013.rs:21:10
|
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
| ^^
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
error: lifetime may not live long enough
- --> $DIR/issue-100013.rs:25:17
+ --> $DIR/issue-100013.rs:23:17
|
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
-...
+LL | async { // a generator checked for autotrait impl `Send`
LL | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
| ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
|
= help: consider adding the following bound: `'a: 'b`
error: lifetime bound not satisfied
- --> $DIR/issue-100013.rs:32:5
+ --> $DIR/issue-100013.rs:29:5
|
LL | / async { // a generator checked for autotrait impl `Send`
-LL | |
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
LL | | async {}.await; // a yield point
LL | | }
| |_____^
|
note: the lifetime defined here...
- --> $DIR/issue-100013.rs:31:18
+ --> $DIR/issue-100013.rs:28:18
|
LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
| ^^
note: ...must outlive the lifetime defined here
- --> $DIR/issue-100013.rs:31:10
+ --> $DIR/issue-100013.rs:28:10
|
LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
| ^^
diff --git a/tests/ui/generic-associated-types/bugs/issue-91762.rs b/tests/ui/generic-associated-types/bugs/issue-91762.rs
index dec668b..8f2cc45 100644
--- a/tests/ui/generic-associated-types/bugs/issue-91762.rs
+++ b/tests/ui/generic-associated-types/bugs/issue-91762.rs
@@ -1,5 +1,5 @@
// check-fail
-// known-bug
+// known-bug: unknown
// We almost certainly want this to pass, but
// it's particularly difficult currently, because we need a way of specifying
@@ -22,7 +22,6 @@
arg = self;
ret = <Self::Base as Functor>::fmap(arg);
- //~^ type annotations needed
}
}
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed
new file mode 100644
index 0000000..6315fcc
--- /dev/null
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+ let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
+ let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
+}
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
new file mode 100644
index 0000000..c12c536
--- /dev/null
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+ let _ = (-10..=10).find(|x: i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
+ let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
+}
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr
new file mode 100644
index 0000000..fb8af4b
--- /dev/null
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr
@@ -0,0 +1,38 @@
+error[E0631]: type mismatch in closure arguments
+ --> $DIR/closure-arg-type-mismatch-issue-45727.rs:3:24
+ |
+LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0);
+ | ^^^^ -------- found signature defined here
+ | |
+ | expected due to this
+ |
+ = note: expected closure signature `for<'a> fn(&'a {integer}) -> _`
+ found closure signature `fn(i32) -> _`
+note: required by a bound in `find`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+help: consider borrowing the argument
+ |
+LL | let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
+ | +
+
+error[E0631]: type mismatch in closure arguments
+ --> $DIR/closure-arg-type-mismatch-issue-45727.rs:4:24
+ |
+LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
+ | ^^^^ ----------- found signature defined here
+ | |
+ | expected due to this
+ |
+ = note: expected closure signature `for<'a> fn(&'a {integer}) -> _`
+ found closure signature `for<'a, 'b, 'c> fn(&'a &'b &'c i32) -> _`
+note: required by a bound in `find`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+help: do not borrow the argument
+ |
+LL - let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
+LL + let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
index fab9b7e..811ff05 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -2,16 +2,18 @@
--> $DIR/closure-arg-type-mismatch.rs:3:14
|
LL | a.iter().map(|_: (u32, u32)| 45);
- | ^^^ ---------------
- | | | |
- | | | help: consider borrowing the argument: `&(u32, u32)`
- | | found signature defined here
+ | ^^^ --------------- found signature defined here
+ | |
| expected due to this
|
= note: expected closure signature `fn(&(u32, u32)) -> _`
found closure signature `fn((u32, u32)) -> _`
note: required by a bound in `map`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+help: consider borrowing the argument
+ |
+LL | a.iter().map(|_: &(u32, u32)| 45);
+ | +
error[E0631]: type mismatch in closure arguments
--> $DIR/closure-arg-type-mismatch.rs:4:14
diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr
index 72fb0e4..a6764a1 100644
--- a/tests/ui/mismatched_types/issue-36053-2.stderr
+++ b/tests/ui/mismatched_types/issue-36053-2.stderr
@@ -2,16 +2,18 @@
--> $DIR/issue-36053-2.rs:7:32
|
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
- | ^^^^^^ ---------
- | | | |
- | | | help: consider borrowing the argument: `&&str`
- | | found signature defined here
+ | ^^^^^^ --------- found signature defined here
+ | |
| expected due to this
|
= note: expected closure signature `for<'a> fn(&'a &str) -> _`
found closure signature `for<'a> fn(&'a str) -> _`
note: required by a bound in `filter`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+help: consider borrowing the argument
+ |
+LL | once::<&str>("str").fuse().filter(|a: &&str| true).count();
+ | +
error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied
--> $DIR/issue-36053-2.rs:7:55
diff --git a/tests/ui/type-alias-impl-trait/outlives-bound-var.rs b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs
new file mode 100644
index 0000000..b8fac45
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs
@@ -0,0 +1,18 @@
+// Here we process outlive obligations involving
+// opaque types with bound vars in substs.
+// This was an ICE.
+//
+// check-pass
+#![feature(type_alias_impl_trait)]
+
+type Ty<'a> = impl Sized + 'a;
+fn define<'a>() -> Ty<'a> {}
+
+// Ty<'^0>: 'static
+fn test1(_: &'static fn(Ty<'_>)) {}
+
+fn test2() {
+ None::<&fn(Ty<'_>)>;
+}
+
+fn main() { }